1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (C) 2008 HTC Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "CameraInput"
20 #include <utils/Log.h>
21 #include <ui/CameraParameters.h>
22 #include <utils/Errors.h>
23 #include <media/mediarecorder.h>
24 #include <ui/ISurface.h>
25 #include <ui/ICamera.h>
26 #include <ui/Camera.h>
27
28 #include "pv_mime_string_utils.h"
29 #include "oscl_dll.h"
30 #include "oscl_tickcount.h"
31
32 #include "android_camera_input.h"
33
34 using namespace android;
35
36
37 // Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()38 OSCL_DLL_ENTRY_POINT_DEFAULT()
39
40 // camera MIO
41 AndroidCameraInput::AndroidCameraInput()
42 : OsclTimerObject(OsclActiveObject::EPriorityNominal, "AndroidCameraInput")
43 {
44 LOGV("constructor(%p)", this);
45 iCmdIdCounter = 0;
46 iPeer = NULL;
47 iThreadLoggedOn = false;
48 iDataEventCounter = 0;
49 iStartTickCount = 0;
50 iTimeStamp = 0;
51 iMilliSecondsPerDataEvent = 0;
52 iMicroSecondsPerDataEvent = 0;
53 iState = STATE_IDLE;
54 mFrameWidth = ANDROID_DEFAULT_FRAME_WIDTH;
55 mFrameHeight= ANDROID_DEFAULT_FRAME_HEIGHT;
56 mFrameRate = ANDROID_DEFAULT_FRAME_RATE;
57 mCamera = NULL;
58 mHeap = 0;
59
60 // FIXME:
61 // mFrameRefCount is redundant. iSendMediaData.empty() can be used to
62 // determine if there are any frames pending in the encoder.
63 mFrameRefCount = 0;
64 mFlags = 0;
65 iFrameQueue.reserve(5);
66 iFrameQueueMutex.Create();
67
68 // setup callback listener
69 mListener = new AndroidCameraInputListener(this);
70 }
71
ReleaseQueuedFrames()72 void AndroidCameraInput::ReleaseQueuedFrames()
73 {
74 LOGV("ReleaseQueuedFrames");
75 iFrameQueueMutex.Lock();
76 while (!iFrameQueue.empty()) {
77 AndroidCameraInputMediaData data = iFrameQueue[0];
78 iFrameQueue.erase(iFrameQueue.begin());
79 #if (LOG_NDEBUG == 0)
80 ssize_t offset = 0;
81 size_t size = 0;
82 sp<IMemoryHeap> heap = data.iFrameBuffer->getMemory(&offset, &size);
83 LOGD("writeComplete: ID = %d, base = %p, offset = %ld, size = %d ReleaseQueuedFrames", heap->getHeapID(), heap->base(), offset, size);
84 #endif
85 mCamera->releaseRecordingFrame(data.iFrameBuffer);
86 }
87 iFrameQueueMutex.Unlock();
88 }
89
~AndroidCameraInput()90 AndroidCameraInput::~AndroidCameraInput()
91 {
92 LOGV("destructor");
93 if (mCamera != NULL) {
94 mCamera->setListener(NULL);
95 ReleaseQueuedFrames();
96 if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
97 LOGV("camera was cold when we started, stopping preview");
98 mCamera->stopPreview();
99 }
100 if (mFlags & FLAGS_SET_CAMERA) {
101 LOGV("unlocking camera to return to app");
102 mCamera->unlock();
103 } else {
104 LOGV("disconnect from camera");
105 mCamera->disconnect();
106 }
107 mFlags = 0;
108 mCamera.clear();
109 }
110 if (mFrameRefCount != 0) {
111 LOGW("mHeap reference count is not zero?!");
112 }
113 iFrameQueueMutex.Close();
114 mListener.clear();
115 }
116
connect(PvmiMIOSession & aSession,PvmiMIOObserver * aObserver)117 PVMFStatus AndroidCameraInput::connect(PvmiMIOSession& aSession,
118 PvmiMIOObserver* aObserver)
119 {
120 LOGV("connect");
121 if (!aObserver) {
122 LOGE("observer is a NULL pointer");
123 return PVMFFailure;
124 }
125
126 int32 err = 0;
127 OSCL_TRY(err, iObservers.push_back(aObserver));
128 OSCL_FIRST_CATCH_ANY(err,
129 LOGE("Out of memory"); return PVMFErrNoMemory);
130
131 // Session ID is the index of observer in the vector
132 aSession = (PvmiMIOSession)(iObservers.size() - 1);
133 return PVMFSuccess;
134 }
135
disconnect(PvmiMIOSession aSession)136 PVMFStatus AndroidCameraInput::disconnect(PvmiMIOSession aSession)
137 {
138 LOGV("disconnect");
139 uint32 index = (uint32) aSession;
140 uint32 size = iObservers.size();
141 if (index >= size) {
142 LOGE("Invalid session ID %d. Valid range is [0, %d]", index, size - 1);
143 return PVMFFailure;
144 }
145
146 iObservers.erase(iObservers.begin() + index);
147 return PVMFSuccess;
148 }
149
createMediaTransfer(PvmiMIOSession & aSession,PvmiKvp * read_formats,int32 read_flags,PvmiKvp * write_formats,int32 write_flags)150 PvmiMediaTransfer* AndroidCameraInput::createMediaTransfer(
151 PvmiMIOSession& aSession,
152 PvmiKvp* read_formats,
153 int32 read_flags,
154 PvmiKvp* write_formats,
155 int32 write_flags)
156 {
157 LOGV("createMediaTransfer");
158 OSCL_UNUSED_ARG(read_formats);
159 OSCL_UNUSED_ARG(read_flags);
160 OSCL_UNUSED_ARG(write_formats);
161 OSCL_UNUSED_ARG(write_flags);
162
163 uint32 index = (uint32) aSession;
164 uint32 size = iObservers.size();
165 if (index >= size) {
166 LOGE("Invalid session ID %d. Valid range is [0, %d]", index, size - 1);
167 OSCL_LEAVE(OsclErrArgument);
168 return NULL;
169 }
170
171 return (PvmiMediaTransfer*)this;
172 }
173
deleteMediaTransfer(PvmiMIOSession & aSession,PvmiMediaTransfer * media_transfer)174 void AndroidCameraInput::deleteMediaTransfer(PvmiMIOSession& aSession,
175 PvmiMediaTransfer* media_transfer)
176 {
177 LOGV("deleteMediaTransfer");
178 uint32 index = (uint32) aSession;
179 uint32 size = iObservers.size();
180 if (index >= size) {
181 LOGE("Invalid session ID %d. Valid range is [0, %d]", index, size - 1);
182 OSCL_LEAVE(OsclErrArgument);
183 return;
184 }
185 if (!media_transfer) {
186 LOGE("media transfer is a NULL pointer");
187 OSCL_LEAVE(OsclErrArgument);
188 }
189
190 // TODO:
191 // 1. I did not see how the media transfer session has been terminated
192 // after this method call.
193 // 2. according to pvmi_mio_control.h, this should also check with there
194 // is any outstanding buffer?
195 }
196
QueryUUID(const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)197 PVMFCommandId AndroidCameraInput::QueryUUID(const PvmfMimeString& aMimeType,
198 Oscl_Vector<PVUuid,
199 OsclMemAllocator>& aUuids,
200 bool aExactUuidsOnly,
201 const OsclAny* aContext)
202 {
203 LOGV("QueryUUID");
204 OSCL_UNUSED_ARG(aMimeType);
205 OSCL_UNUSED_ARG(aExactUuidsOnly);
206
207 int32 err = 0;
208 OSCL_TRY(err, aUuids.push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID););
209 OSCL_FIRST_CATCH_ANY(err,
210 LOGE("Out of memory"); OSCL_LEAVE(OsclErrNoMemory));
211
212 return AddCmdToQueue(CMD_QUERY_UUID, aContext);
213 }
214
QueryInterface(const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)215 PVMFCommandId AndroidCameraInput::QueryInterface(const PVUuid& aUuid,
216 PVInterface*& aInterfacePtr,
217 const OsclAny* aContext)
218 {
219 LOGV("QueryInterface");
220 if (aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) {
221 PvmiCapabilityAndConfig*
222 myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*,this);
223
224 aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface);
225 } else {
226 aInterfacePtr = NULL;
227 }
228
229 return AddCmdToQueue(CMD_QUERY_INTERFACE,
230 aContext,
231 (OsclAny*)&aInterfacePtr);
232 }
233
Init(const OsclAny * aContext)234 PVMFCommandId AndroidCameraInput::Init(const OsclAny* aContext)
235 {
236 LOGV("Init");
237 if (iState != STATE_IDLE) {
238 LOGE("Init called in an invalid state(%d)", iState);
239 OSCL_LEAVE(OsclErrInvalidState);
240 return -1;
241 }
242
243 return AddCmdToQueue(CMD_INIT, aContext);
244 }
245
246
Start(const OsclAny * aContext)247 PVMFCommandId AndroidCameraInput::Start(const OsclAny* aContext)
248 {
249 LOGV("Start");
250 if (iState != STATE_INITIALIZED && iState != STATE_PAUSED) {
251 LOGE("Start called in an invalid state(%d)", iState);
252 OSCL_LEAVE(OsclErrInvalidState);
253 return -1;
254 }
255
256 return AddCmdToQueue(CMD_START, aContext);
257 }
258
Pause(const OsclAny * aContext)259 PVMFCommandId AndroidCameraInput::Pause(const OsclAny* aContext)
260 {
261 LOGV("Pause");
262 if (iState != STATE_STARTED) {
263 LOGE("Pause called in an invalid state(%d)", iState);
264 OSCL_LEAVE(OsclErrInvalidState);
265 return -1;
266 }
267
268 return AddCmdToQueue(CMD_PAUSE, aContext);
269 }
270
Flush(const OsclAny * aContext)271 PVMFCommandId AndroidCameraInput::Flush(const OsclAny* aContext)
272 {
273 LOGV("Flush");
274 if (iState != STATE_STARTED && iState != STATE_PAUSED) {
275 LOGE("Flush called in an invalid state(%d)", iState);
276 OSCL_LEAVE(OsclErrInvalidState);
277 return -1;
278 }
279
280 return AddCmdToQueue(CMD_FLUSH, aContext);
281 }
282
Reset(const OsclAny * aContext)283 PVMFCommandId AndroidCameraInput::Reset(const OsclAny* aContext)
284 {
285 LOGV("Reset");
286 return AddCmdToQueue(CMD_RESET, aContext);
287 }
288
DiscardData(PVMFTimestamp aTimestamp,const OsclAny * aContext)289 PVMFCommandId AndroidCameraInput::DiscardData(PVMFTimestamp aTimestamp,
290 const OsclAny* aContext)
291 {
292 LOGV("DiscardData with time stamp");
293 OSCL_UNUSED_ARG(aContext);
294 OSCL_UNUSED_ARG(aTimestamp);
295 OSCL_LEAVE(OsclErrNotSupported);
296 return -1;
297 }
298
DiscardData(const OsclAny * aContext)299 PVMFCommandId AndroidCameraInput::DiscardData(const OsclAny* aContext)
300 {
301 LOGV("DiscardData");
302 OSCL_UNUSED_ARG(aContext);
303 OSCL_LEAVE(OsclErrNotSupported);
304 return -1;
305 }
306
Stop(const OsclAny * aContext)307 PVMFCommandId AndroidCameraInput::Stop(const OsclAny* aContext)
308 {
309 LOGV("Stop");
310 if (iState != STATE_STARTED && iState != STATE_PAUSED) {
311 LOGE("Stop called in an invalid state(%d)", iState);
312 OSCL_LEAVE(OsclErrInvalidState);
313 return -1;
314 }
315
316 return AddCmdToQueue(CMD_STOP, aContext);
317 }
318
ThreadLogon()319 void AndroidCameraInput::ThreadLogon()
320 {
321 LOGV("ThreadLogon");
322 if (!iThreadLoggedOn) {
323 AddToScheduler();
324 iThreadLoggedOn = true;
325 }
326 }
327
ThreadLogoff()328 void AndroidCameraInput::ThreadLogoff()
329 {
330 LOGV("ThreadLogoff");
331 if (iThreadLoggedOn) {
332 RemoveFromScheduler();
333 iThreadLoggedOn = false;
334 }
335 }
336
CancelAllCommands(const OsclAny * aContext)337 PVMFCommandId AndroidCameraInput::CancelAllCommands(const OsclAny* aContext)
338 {
339 LOGV("CancelAllCommands");
340 OSCL_UNUSED_ARG(aContext);
341 OSCL_LEAVE(OsclErrNotSupported);
342 return -1;
343 }
344
CancelCommand(PVMFCommandId aCmdId,const OsclAny * aContext)345 PVMFCommandId AndroidCameraInput::CancelCommand(PVMFCommandId aCmdId,
346 const OsclAny* aContext)
347 {
348 LOGV("CancelCommand");
349 OSCL_UNUSED_ARG(aCmdId);
350 OSCL_UNUSED_ARG(aContext);
351 OSCL_LEAVE(OsclErrNotSupported);
352 return -1;
353 }
354
setPeer(PvmiMediaTransfer * aPeer)355 void AndroidCameraInput::setPeer(PvmiMediaTransfer* aPeer)
356 {
357 LOGV("setPeer iPeer %p aPeer %p", iPeer, aPeer);
358 if(iPeer && aPeer){
359 LOGE("setPeer iPeer %p aPeer %p", iPeer, aPeer);
360 OSCL_LEAVE(OsclErrGeneral);
361 return;
362 }
363
364 iPeer = aPeer;
365 }
366
useMemoryAllocators(OsclMemAllocator * write_alloc)367 void AndroidCameraInput::useMemoryAllocators(OsclMemAllocator* write_alloc)
368 {
369 LOGV("useMemoryAllocators");
370 OSCL_UNUSED_ARG(write_alloc);
371 OSCL_LEAVE(OsclErrNotSupported);
372 }
373
writeAsync(uint8 aFormatType,int32 aFormatIndex,uint8 * aData,uint32 aDataLen,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)374 PVMFCommandId AndroidCameraInput::writeAsync(uint8 aFormatType,
375 int32 aFormatIndex,
376 uint8* aData,
377 uint32 aDataLen,
378 const PvmiMediaXferHeader& data_header_info,
379 OsclAny* aContext)
380 {
381 LOGV("writeAsync");
382 OSCL_UNUSED_ARG(aFormatType);
383 OSCL_UNUSED_ARG(aFormatIndex);
384 OSCL_UNUSED_ARG(aData);
385 OSCL_UNUSED_ARG(aDataLen);
386 OSCL_UNUSED_ARG(data_header_info);
387 OSCL_UNUSED_ARG(aContext);
388 // This is an active data source. writeAsync is not supported.
389 OSCL_LEAVE(OsclErrNotSupported);
390 return -1;
391 }
392
writeComplete(PVMFStatus aStatus,PVMFCommandId write_cmd_id,OsclAny * aContext)393 void AndroidCameraInput::writeComplete(PVMFStatus aStatus,
394 PVMFCommandId write_cmd_id,
395 OsclAny* aContext)
396 {
397 LOGV("writeComplete");
398 OSCL_UNUSED_ARG(aContext);
399
400 iFrameQueueMutex.Lock();
401 if (iSentMediaData.empty()) {
402 LOGE("Nothing to complete");
403 iFrameQueueMutex.Unlock();
404 return;
405 }
406
407 AndroidCameraInputMediaData data = iSentMediaData[0];
408 #if (LOG_NDEBUG == 0)
409 ssize_t offset = 0;
410 size_t size = 0;
411 sp<IMemoryHeap> heap = data.iFrameBuffer->getMemory(&offset, &size);
412 LOGD("writeComplete: ID = %d, base = %p, offset = %ld, size = %d", heap->getHeapID(), heap->base(), offset, size);
413 #endif
414 mCamera->releaseRecordingFrame(data.iFrameBuffer);
415
416 if (mFrameRefCount) {
417 --mFrameRefCount;
418 }
419 //LOGV("@@@@@@@@@@@@@ decrementing frame reference count: %d @@@@@@@@@@@@", mFrameRefCount);
420 if (mFrameRefCount <= 0) {
421 //LOGV("decrement the reference count for mHeap");
422 mFrameRefCount = 0;
423 mHeap.clear();
424 }
425
426 iSentMediaData.erase(iSentMediaData.begin());
427 iFrameQueueMutex.Unlock();
428
429 // reference count is always updated, even if the write fails
430 if (aStatus != PVMFSuccess) {
431 LOGE("writeAsync failed. aStatus=%d", aStatus);
432 }
433 }
434
readAsync(uint8 * data,uint32 max_data_len,OsclAny * aContext,int32 * formats,uint16 num_formats)435 PVMFCommandId AndroidCameraInput::readAsync(uint8* data,
436 uint32 max_data_len,
437 OsclAny* aContext,
438 int32* formats,
439 uint16 num_formats)
440 {
441 LOGV("readAsync");
442 OSCL_UNUSED_ARG(data);
443 OSCL_UNUSED_ARG(max_data_len);
444 OSCL_UNUSED_ARG(aContext);
445 OSCL_UNUSED_ARG(formats);
446 OSCL_UNUSED_ARG(num_formats);
447 // This is an active data source. readAsync is not supported.
448 OSCL_LEAVE(OsclErrNotSupported);
449 return -1;
450 }
451
readComplete(PVMFStatus aStatus,PVMFCommandId read_cmd_id,int32 format_index,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)452 void AndroidCameraInput::readComplete(PVMFStatus aStatus,
453 PVMFCommandId read_cmd_id,
454 int32 format_index,
455 const PvmiMediaXferHeader& data_header_info,
456 OsclAny* aContext)
457 {
458 LOGV("readComplete");
459 OSCL_UNUSED_ARG(aStatus);
460 OSCL_UNUSED_ARG(read_cmd_id);
461 OSCL_UNUSED_ARG(format_index);
462 OSCL_UNUSED_ARG(data_header_info);
463 OSCL_UNUSED_ARG(aContext);
464 // This is an active data source. readComplete is not supported.
465 OSCL_LEAVE(OsclErrNotSupported);
466 return;
467 }
468
statusUpdate(uint32 status_flags)469 void AndroidCameraInput::statusUpdate(uint32 status_flags)
470 {
471 LOGV("statusUpdate");
472 OSCL_UNUSED_ARG(status_flags);
473 // Ideally this routine should update the status of media input component.
474 // It should check then for the status. If media input buffer is consumed,
475 // media input object should be resheduled.
476 // Since the Media fileinput component is designed with single buffer, two
477 // asynchronous reads are not possible. So this function will not be
478 // requiredand hence not been implemented.
479 OSCL_LEAVE(OsclErrNotSupported);
480 }
481
cancelCommand(PVMFCommandId aCmdId)482 void AndroidCameraInput::cancelCommand(PVMFCommandId aCmdId)
483 {
484 LOGV("cancelCommand");
485 OSCL_UNUSED_ARG(aCmdId);
486
487 // This cancel command ( with a small "c" in cancel ) is for the media
488 // transfer interface. implementation is similar to the cancel command
489 // of the media I/O interface.
490 OSCL_LEAVE(OsclErrNotSupported);
491 }
492
cancelAllCommands()493 void AndroidCameraInput::cancelAllCommands()
494 {
495 LOGV("cancelAllCommands");
496 OSCL_LEAVE(OsclErrNotSupported);
497 }
498
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)499 void AndroidCameraInput::setObserver(
500 PvmiConfigAndCapabilityCmdObserver* aObserver)
501 {
502 LOGV("setObserver");
503 OSCL_UNUSED_ARG(aObserver);
504 }
505
getParametersSync(PvmiMIOSession session,PvmiKeyType identifier,PvmiKvp * & params,int & num_params,PvmiCapabilityContext context)506 PVMFStatus AndroidCameraInput::getParametersSync(PvmiMIOSession session,
507 PvmiKeyType identifier,
508 PvmiKvp*& params,
509 int& num_params,
510 PvmiCapabilityContext context)
511 {
512 LOGV("getParametersSync");
513 OSCL_UNUSED_ARG(session);
514 OSCL_UNUSED_ARG(context);
515
516 params = NULL;
517 num_params = 0;
518 PVMFStatus status = PVMFFailure;
519
520 if (!pv_mime_strcmp(identifier, OUTPUT_FORMATS_CAP_QUERY) ||
521 !pv_mime_strcmp(identifier, OUTPUT_FORMATS_CUR_QUERY)) {
522 num_params = 1;
523 status = AllocateKvp(params, (PvmiKeyType)OUTPUT_FORMATS_VALTYPE, num_params);
524 if (status != PVMFSuccess) {
525 LOGE("AllocateKvp failed for OUTPUT_FORMATS_VALTYP");
526 return status;
527 }
528 params[0].value.pChar_value = (char*)ANDROID_VIDEO_FORMAT;
529 } else if (!pv_mime_strcmp(identifier, VIDEO_OUTPUT_WIDTH_CUR_QUERY)) {
530 num_params = 1;
531 status = AllocateKvp(params, (PvmiKeyType)VIDEO_OUTPUT_WIDTH_CUR_VALUE, num_params);
532 if (status != PVMFSuccess) {
533 LOGE("AllocateKvp failed for VIDEO_OUTPUT_WIDTH_CUR_VALUE");
534 return status;
535 }
536 params[0].value.uint32_value = mFrameWidth;
537 } else if (!pv_mime_strcmp(identifier, VIDEO_OUTPUT_HEIGHT_CUR_QUERY)) {
538 num_params = 1;
539 status = AllocateKvp(params, (PvmiKeyType)VIDEO_OUTPUT_HEIGHT_CUR_VALUE, num_params);
540 if (status != PVMFSuccess) {
541 LOGE("AllocateKvp failed for VIDEO_OUTPUT_HEIGHT_CUR_VALUE");
542 return status;
543 }
544 params[0].value.uint32_value = mFrameHeight;
545 } else if (!pv_mime_strcmp(identifier, VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY)) {
546 num_params = 1;
547 status = AllocateKvp(params,
548 (PvmiKeyType)VIDEO_OUTPUT_FRAME_RATE_CUR_VALUE, num_params);
549 if (status != PVMFSuccess) {
550 LOGE("AllocateKvp failed for VIDEO_OUTPUT_FRAME_RATE_CUR_VALUE");
551 return status;
552 }
553 params[0].value.float_value = mFrameRate;
554 } else if (!pv_mime_strcmp(identifier, OUTPUT_TIMESCALE_CUR_QUERY)) {
555 num_params = 1;
556 status = AllocateKvp(params, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_VALUE, num_params);
557 if (status != PVMFSuccess) {
558 LOGE("AllocateKvp failed for OUTPUT_TIMESCALE_CUR_VALUE");
559 return status;
560 }
561 // TODO:
562 // is it okay to hardcode this as the timescale?
563 params[0].value.uint32_value = 1000;
564 }
565
566 return status;
567 }
568
releaseParameters(PvmiMIOSession session,PvmiKvp * parameters,int num_elements)569 PVMFStatus AndroidCameraInput::releaseParameters(PvmiMIOSession session,
570 PvmiKvp* parameters,
571 int num_elements)
572 {
573 LOGV("releaseParameters");
574 OSCL_UNUSED_ARG(session);
575 OSCL_UNUSED_ARG(num_elements);
576
577 if (!parameters) {
578 LOGE("parameters is a NULL pointer");
579 return PVMFFailure;
580 }
581 iAlloc.deallocate((OsclAny*)parameters);
582 return PVMFSuccess;
583 }
584
createContext(PvmiMIOSession session,PvmiCapabilityContext & context)585 void AndroidCameraInput::createContext(PvmiMIOSession session,
586 PvmiCapabilityContext& context)
587 {
588 LOGV("createContext");
589 OSCL_UNUSED_ARG(session);
590 OSCL_UNUSED_ARG(context);
591 }
592
setContextParameters(PvmiMIOSession session,PvmiCapabilityContext & context,PvmiKvp * parameters,int num_parameter_elements)593 void AndroidCameraInput::setContextParameters(PvmiMIOSession session,
594 PvmiCapabilityContext& context,
595 PvmiKvp* parameters,
596 int num_parameter_elements)
597 {
598 LOGV("setContextParameters");
599 OSCL_UNUSED_ARG(session);
600 OSCL_UNUSED_ARG(context);
601 OSCL_UNUSED_ARG(parameters);
602 OSCL_UNUSED_ARG(num_parameter_elements);
603 }
604
DeleteContext(PvmiMIOSession session,PvmiCapabilityContext & context)605 void AndroidCameraInput::DeleteContext(PvmiMIOSession session,
606 PvmiCapabilityContext& context)
607 {
608 LOGV("DeleteContext");
609 OSCL_UNUSED_ARG(session);
610 OSCL_UNUSED_ARG(context);
611 }
612
setParametersSync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements,PvmiKvp * & ret_kvp)613 void AndroidCameraInput::setParametersSync(PvmiMIOSession session,
614 PvmiKvp* parameters,
615 int num_elements,
616 PvmiKvp*& ret_kvp)
617 {
618 LOGV("setParametersSync");
619 OSCL_UNUSED_ARG(session);
620 PVMFStatus status = PVMFSuccess;
621 ret_kvp = NULL;
622 for (int32 i = 0; i < num_elements; ++i) {
623 status = VerifyAndSetParameter(&(parameters[i]), true);
624 if (status != PVMFSuccess) {
625 LOGE("VerifiyAndSetParameter failed on parameter #%d", i);
626 ret_kvp = &(parameters[i]);
627 OSCL_LEAVE(OsclErrArgument);
628 return;
629 }
630 }
631 }
632
setParametersAsync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements,PvmiKvp * & ret_kvp,OsclAny * context)633 PVMFCommandId AndroidCameraInput::setParametersAsync(PvmiMIOSession session,
634 PvmiKvp* parameters,
635 int num_elements,
636 PvmiKvp*& ret_kvp,
637 OsclAny* context)
638 {
639 LOGV("setParametersAsync");
640 OSCL_UNUSED_ARG(session);
641 OSCL_UNUSED_ARG(parameters);
642 OSCL_UNUSED_ARG(num_elements);
643 OSCL_UNUSED_ARG(ret_kvp);
644 OSCL_UNUSED_ARG(context);
645 OSCL_LEAVE(OsclErrNotSupported);
646 return -1;
647 }
648
getCapabilityMetric(PvmiMIOSession session)649 uint32 AndroidCameraInput::getCapabilityMetric (PvmiMIOSession session)
650 {
651 LOGV("getCapabilityMetric");
652 OSCL_UNUSED_ARG(session);
653 return 0;
654 }
655
verifyParametersSync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements)656 PVMFStatus AndroidCameraInput::verifyParametersSync(PvmiMIOSession session,
657 PvmiKvp* parameters,
658 int num_elements)
659 {
660 LOGV("verifyParametersSync");
661 OSCL_UNUSED_ARG(session);
662 OSCL_UNUSED_ARG(parameters);
663 OSCL_UNUSED_ARG(num_elements);
664 return PVMFErrNotSupported;
665 }
666
667
SetFrameSize(int w,int h)668 void AndroidCameraInput::SetFrameSize(int w, int h)
669 {
670 LOGV("SetFrameSize");
671 if (iState != STATE_IDLE) {
672 LOGE("SetFrameSize called in an invalid state(%d)", iState);
673 return;
674 }
675
676 mFrameWidth = w;
677 mFrameHeight = h;
678 FrameSizeChanged();
679 }
680
SetFrameRate(int fps)681 void AndroidCameraInput::SetFrameRate(int fps)
682 {
683 LOGV("SetFrameRate");
684 if (iState != STATE_IDLE) {
685 LOGE("SetFrameRate called in an invalid state(%d)", iState);
686 return;
687 }
688
689 mFrameRate = (float)fps;
690 }
691
FrameSizeChanged()692 void AndroidCameraInput::FrameSizeChanged()
693 {
694 LOGV("FrameSizeChanged");
695 if (iState != STATE_IDLE) {
696 LOGE("FrameSizeChanged called in an invalid state(%d)", iState);
697 return;
698 }
699
700 // Reinitialize the preview surface in case it was set up before now
701 if (mSurface != NULL) {
702 SetPreviewSurface(mSurface);
703 }
704 }
705
Run()706 void AndroidCameraInput::Run()
707 {
708 LOGV("Run");
709
710 // dequeue frame buffers and write to peer
711 if (NULL != iPeer) {
712 iFrameQueueMutex.Lock();
713 while (!iFrameQueue.empty()) {
714 AndroidCameraInputMediaData data = iFrameQueue[0];
715
716 uint32 writeAsyncID = 0;
717 OsclLeaveCode error = OsclErrNone;
718 uint8 *ptr = (uint8*) (data.iFrameBuffer->pointer());
719 if (ptr) {
720 OSCL_TRY(error,writeAsyncID = iPeer->writeAsync(PVMI_MEDIAXFER_FMT_TYPE_DATA, 0, ptr,
721 data.iFrameSize, data.iXferHeader););
722 } else {
723 //FIXME Check why camera sends NULL frames
724 LOGE("Ln %d ERROR null pointer", __LINE__);
725 error = OsclErrBadHandle;
726 }
727
728 if (OsclErrNone == error) {
729 iFrameQueue.erase(iFrameQueue.begin());
730 data.iId = writeAsyncID;
731 iSentMediaData.push_back(data);
732 ++mFrameRefCount;
733 LOGV("Ln %d Run writeAsync mFrameRefCount %d writeAsyncID %d", __LINE__, mFrameRefCount, writeAsyncID);
734 } else {
735 //FIXME resend the frame later if ( OsclErrBusy == error)
736 LOGE("Ln %d Run writeAsync error %d mFrameRefCount %d", __LINE__, error, mFrameRefCount);
737 //release buffer immediately if write fails
738 mCamera->releaseRecordingFrame(data.iFrameBuffer);
739 iFrameQueue.erase(iFrameQueue.begin());
740 break;
741 }
742 }
743 iFrameQueueMutex.Unlock();
744 }
745
746 PVMFStatus status = PVMFFailure;
747
748 if (!iCmdQueue.empty()) {
749 AndroidCameraInputCmd cmd = iCmdQueue[0];
750 iCmdQueue.erase(iCmdQueue.begin());
751
752 switch(cmd.iType) {
753
754 case CMD_INIT:
755 status = DoInit();
756 break;
757
758 case CMD_START:
759 status = DoStart();
760 break;
761
762 case CMD_PAUSE:
763 status = DoPause();
764 break;
765
766 case CMD_FLUSH:
767 status = DoFlush(cmd);
768 break;
769
770 case CMD_RESET:
771 status = DoReset();
772 break;
773
774 case CMD_STOP:
775 status = DoStop(cmd);
776 break;
777
778 case DATA_EVENT:
779 // this is internal only - don't send RequestCompleted
780 DoRead();
781 status = PVMFPending;
782 break;
783
784 case CMD_QUERY_UUID:
785 case CMD_QUERY_INTERFACE:
786 status = PVMFSuccess;
787 break;
788
789 // these commands all fail
790 case CMD_CANCEL_ALL_COMMANDS:
791 case CMD_CANCEL_COMMAND:
792 default:
793 break;
794 }
795 // do RequestCompleted unless command is still pending
796 if (status != PVMFPending) {
797 DoRequestCompleted(cmd, status);
798 }
799 }
800
801 if (!iCmdQueue.empty()) {
802 // Run again if there are more things to process
803 RunIfNotReady();
804 }
805 }
806
AddCmdToQueue(AndroidCameraInputCmdType aType,const OsclAny * aContext,OsclAny * aData)807 PVMFCommandId AndroidCameraInput::AddCmdToQueue(AndroidCameraInputCmdType aType,
808 const OsclAny* aContext,
809 OsclAny* aData)
810 {
811 LOGV("AddCmdToQueue");
812 if (aType == DATA_EVENT) {
813 LOGE("Invalid argument");
814 OSCL_LEAVE(OsclErrArgument);
815 return -1;
816 }
817
818 AndroidCameraInputCmd cmd;
819 cmd.iType = aType;
820 cmd.iContext = OSCL_STATIC_CAST(OsclAny*, aContext);
821 cmd.iData = aData;
822 cmd.iId = iCmdIdCounter;
823 ++iCmdIdCounter;
824
825 // TODO:
826 // Check against out of memory failure
827 int err = 0;
828 OSCL_TRY(err, iCmdQueue.push_back(cmd));
829 OSCL_FIRST_CATCH_ANY(err, LOGE("Out of memory"); return -1;);
830 RunIfNotReady();
831 return cmd.iId;
832 }
833
AddDataEventToQueue(uint32 aMicroSecondsToEvent)834 void AndroidCameraInput::AddDataEventToQueue(uint32 aMicroSecondsToEvent)
835 {
836 LOGV("AddDataEventToQueue");
837 AndroidCameraInputCmd cmd;
838 cmd.iType = DATA_EVENT;
839
840 int err = 0;
841 OSCL_TRY(err, iCmdQueue.push_back(cmd));
842 OSCL_FIRST_CATCH_ANY(err, LOGE("Out of memory"); return;);
843 RunIfNotReady(aMicroSecondsToEvent);
844 }
845
DoRequestCompleted(const AndroidCameraInputCmd & aCmd,PVMFStatus aStatus,OsclAny * aEventData)846 void AndroidCameraInput::DoRequestCompleted(const AndroidCameraInputCmd& aCmd, PVMFStatus aStatus, OsclAny* aEventData)
847 {
848 LOGV("DoRequestCompleted");
849 PVMFCmdResp response(aCmd.iId, aCmd.iContext, aStatus, aEventData);
850
851 for (uint32 i = 0; i < iObservers.size(); i++) {
852 iObservers[i]->RequestCompleted(response);
853 }
854 }
855
DoInit()856 PVMFStatus AndroidCameraInput::DoInit()
857 {
858 LOGV("DoInit()");
859 iState = STATE_INITIALIZED;
860 iMilliSecondsPerDataEvent = (int32)(1000 / mFrameRate);
861 iMicroSecondsPerDataEvent = (int32)(1000000 / mFrameRate);
862 iDataEventCounter = 0;
863
864 // create a camera if the app didn't supply one
865 if (mCamera == 0) {
866 mCamera = Camera::connect();
867 }
868
869 // always call setPreviewDisplay() regardless whether mCamera is just created or not
870 // return failure if no display surface is available
871 if (mCamera != NULL && mSurface != NULL) {
872 mCamera->setPreviewDisplay(mSurface);
873 } else {
874 if (mCamera == NULL) {
875 LOGE("Camera is not available");
876 } else if (mSurface == NULL) {
877 LOGE("No surface is available for display");
878 }
879 return PVMFFailure;
880 }
881
882 LOGD("Intended mFrameWidth=%d, mFrameHeight=%d ",mFrameWidth, mFrameHeight);
883 String8 s = mCamera->getParameters();
884 if (s.length() == 0) {
885 LOGE("Failed to get camera(%p) parameters", mCamera.get());
886 return PVMFFailure;
887 }
888 CameraParameters p(s);
889 p.setPreviewSize(mFrameWidth, mFrameHeight);
890 s = p.flatten();
891 if (mCamera->setParameters(s) != NO_ERROR) {
892 LOGE("Failed to set camera(%p) parameters", mCamera.get());
893 return PVMFFailure;
894 }
895
896 // Since we may not honor the preview size that app has requested
897 // It is a good idea to get the actual preview size and used it
898 // for video recording.
899 CameraParameters newCameraParam(mCamera->getParameters());
900 int32 width, height;
901 newCameraParam.getPreviewSize(&width, &height);
902 if (width < 0 || height < 0) {
903 LOGE("Failed to get camera(%p) preview size", mCamera.get());
904 return PVMFFailure;
905 }
906 if (width != mFrameWidth || height != mFrameHeight) {
907 LOGE("Mismatch between the intended frame size (%dx%d) and the available frame size (%dx%d)", mFrameWidth, mFrameHeight, width, height);
908 return PVMFFailure;
909 }
910 LOGD("Actual mFrameWidth=%d, mFrameHeight=%d ",mFrameWidth, mFrameHeight);
911 if (mCamera->startPreview() != NO_ERROR) {
912 LOGE("Failed to start camera(%p) preview", mCamera.get());
913 return PVMFFailure;
914 }
915 return PVMFSuccess;
916 }
917
DoStart()918 PVMFStatus AndroidCameraInput::DoStart()
919 {
920 LOGV("DoStart");
921 PVMFStatus status = PVMFFailure;
922 if (mCamera == NULL) {
923 status = PVMFFailure;
924 } else {
925 mCamera->setListener(mListener);
926 if (mCamera->startRecording() != NO_ERROR) {
927 status = PVMFFailure;
928 } else {
929 iState = STATE_STARTED;
930 status = PVMFSuccess;
931 }
932 }
933 iStartTickCount = (uint32) (systemTime() / 1000000L);
934 AddDataEventToQueue(iMilliSecondsPerDataEvent);
935 return status;
936 }
937
DoPause()938 PVMFStatus AndroidCameraInput::DoPause()
939 {
940 LOGV("DoPause");
941 iState = STATE_PAUSED;
942 return PVMFSuccess;
943 }
944
945 // Does this work for reset?
DoReset()946 PVMFStatus AndroidCameraInput::DoReset()
947 {
948 LOGV("DoReset");
949 iDataEventCounter = 0;
950 if ( (iState == STATE_STARTED) || (iState == STATE_PAUSED) ) {
951 if (mCamera != NULL) {
952 mCamera->setListener(NULL);
953 mCamera->stopRecording();
954 ReleaseQueuedFrames();
955 }
956 }
957 while(!iCmdQueue.empty())
958 {
959 AndroidCameraInputCmd cmd = iCmdQueue[0];
960 iCmdQueue.erase(iCmdQueue.begin());
961 }
962 Cancel();
963 iState = STATE_IDLE;
964 return PVMFSuccess;
965 }
966
DoFlush(const AndroidCameraInputCmd & aCmd)967 PVMFStatus AndroidCameraInput::DoFlush(const AndroidCameraInputCmd& aCmd)
968 {
969 LOGV("DoFlush");
970 // This method should stop capturing media data but continue to send
971 // captured media data that is already in buffer and then go to
972 // stopped state.
973 // However, in this case of file input we do not have such a buffer for
974 // captured data, so this behaves the same way as stop.
975 return DoStop(aCmd);
976 }
977
DoStop(const AndroidCameraInputCmd & aCmd)978 PVMFStatus AndroidCameraInput::DoStop(const AndroidCameraInputCmd& aCmd)
979 {
980 LOGV("DoStop");
981 iDataEventCounter = 0;
982 if (mCamera != NULL) {
983 mCamera->setListener(NULL);
984 mCamera->stopRecording();
985 ReleaseQueuedFrames();
986 }
987 iState = STATE_STOPPED;
988 return PVMFSuccess;
989 }
990
DoRead()991 PVMFStatus AndroidCameraInput::DoRead()
992 {
993 LOGV("DoRead");
994 return PVMFSuccess;
995 }
996
AllocateKvp(PvmiKvp * & aKvp,PvmiKeyType aKey,int32 aNumParams)997 PVMFStatus AndroidCameraInput::AllocateKvp(PvmiKvp*& aKvp,
998 PvmiKeyType aKey,
999 int32 aNumParams)
1000 {
1001 LOGV("AllocateKvp");
1002 uint8* buf = NULL;
1003 uint32 keyLen = oscl_strlen(aKey) + 1;
1004 int32 err = 0;
1005
1006 OSCL_TRY(err,
1007 buf = (uint8*)iAlloc.allocate(aNumParams * (sizeof(PvmiKvp) + keyLen));
1008 if (!buf) {
1009 OSCL_LEAVE(OsclErrNoMemory);
1010 }
1011 );
1012 OSCL_FIRST_CATCH_ANY(err,
1013 LOGE("kvp allocation failed");
1014 return PVMFErrNoMemory;
1015 );
1016
1017 PvmiKvp* curKvp = aKvp = new (buf) PvmiKvp;
1018 buf += sizeof(PvmiKvp);
1019 for (int32 i = 1; i < aNumParams; ++i) {
1020 curKvp += i;
1021 curKvp = new (buf) PvmiKvp;
1022 buf += sizeof(PvmiKvp);
1023 }
1024
1025 for (int32 i = 0; i < aNumParams; ++i) {
1026 aKvp[i].key = (char*)buf;
1027 oscl_strncpy(aKvp[i].key, aKey, keyLen);
1028 buf += keyLen;
1029 }
1030
1031 return PVMFSuccess;
1032 }
1033
VerifyAndSetParameter(PvmiKvp * aKvp,bool aSetParam)1034 PVMFStatus AndroidCameraInput::VerifyAndSetParameter(PvmiKvp* aKvp,
1035 bool aSetParam)
1036 {
1037 LOGV("VerifyAndSetParameter");
1038
1039 if (!aKvp) {
1040 LOGE("Invalid key-value pair");
1041 return PVMFFailure;
1042 }
1043
1044 if (!pv_mime_strcmp(aKvp->key, OUTPUT_FORMATS_VALTYPE)) {
1045 if(pv_mime_strcmp(aKvp->value.pChar_value, ANDROID_VIDEO_FORMAT) == 0) {
1046 return PVMFSuccess;
1047 } else {
1048 LOGE("Unsupported format %d", aKvp->value.uint32_value);
1049 return PVMFFailure;
1050 }
1051 }
1052
1053 LOGE("Unsupported parameter(%s)", aKvp->key);
1054 return PVMFFailure;
1055 }
1056
SetPreviewSurface(const sp<android::ISurface> & surface)1057 void AndroidCameraInput::SetPreviewSurface(const sp<android::ISurface>& surface)
1058 {
1059 LOGV("SetPreviewSurface");
1060 mSurface = surface;
1061
1062 if (mCamera != NULL) {
1063 mCamera->setPreviewDisplay(surface);
1064 }
1065 }
1066
SetCamera(const sp<android::ICamera> & camera)1067 PVMFStatus AndroidCameraInput::SetCamera(const sp<android::ICamera>& camera)
1068 {
1069 LOGV("SetCamera");
1070 mFlags &= ~ FLAGS_SET_CAMERA | FLAGS_HOT_CAMERA;
1071 if (camera == NULL) {
1072 LOGV("camera is NULL");
1073 return PVMFErrArgument;
1074 }
1075
1076 // Connect our client to the camera remote
1077 mCamera = Camera::create(camera);
1078 if (mCamera == NULL) {
1079 LOGE("Unable to connect to camera");
1080 return PVMFErrNoResources;
1081 }
1082
1083 LOGV("Connected to camera");
1084 mFlags |= FLAGS_SET_CAMERA;
1085 if (mCamera->previewEnabled()) {
1086 mFlags |= FLAGS_HOT_CAMERA;
1087 LOGV("camera is hot");
1088 }
1089 return PVMFSuccess;
1090 }
1091
postWriteAsync(nsecs_t timestamp,const sp<IMemory> & frame)1092 PVMFStatus AndroidCameraInput::postWriteAsync(nsecs_t timestamp, const sp<IMemory>& frame)
1093 {
1094 LOGV("postWriteAsync");
1095
1096 if (frame == NULL) {
1097 LOGE("frame is a NULL pointer");
1098 return PVMFFailure;
1099 }
1100
1101 // release the received recording frame right way
1102 // if recording has not been started yet or recording has already finished
1103 if((!iPeer) || (!isRecorderStarting()) ) {
1104 LOGV("Recording is not started, so recording frame is dropped");
1105 mCamera->releaseRecordingFrame(frame);
1106 return PVMFSuccess;
1107 }
1108
1109 // calculate timestamp as offset from start time
1110 uint32 t = (uint32)(timestamp / 1000000L) - iStartTickCount;
1111
1112 // Make sure that no two samples have the same timestamp
1113 if (iDataEventCounter != 0) {
1114 if (iTimeStamp != t) {
1115 iTimeStamp = t;
1116 } else {
1117 ++iTimeStamp;
1118 }
1119 }
1120
1121 // get memory offset for frame buffer
1122 ssize_t offset = 0;
1123 size_t size = 0;
1124 sp<IMemoryHeap> heap = frame->getMemory(&offset, &size);
1125 LOGV("postWriteAsync: ID = %d, base = %p, offset = %p, size = %d pointer %p", heap->getHeapID(), heap->base(), offset, size, frame->pointer());
1126 //LOGV("postWriteAsync: ID = %d, base = %p, offset = %p, size = %d", heap->getHeapID(), heap->base(), offset, size);
1127
1128 //LOGV("@@@@@@@@@@@@@ incrementing reference count (%d) @@@@@@@@@@@@@@@", mFrameRefCount);
1129 if (mHeap == 0) {
1130 //LOGV("initialize the reference to frame heap memory");
1131 mHeap = heap;
1132 } else if (mHeap != heap) {
1133 LOGE("mHeap != heap");
1134 return PVMFFailure;
1135 }
1136
1137 // queue data to be sent to peer
1138 AndroidCameraInputMediaData data;
1139 data.iXferHeader.seq_num = iDataEventCounter++;
1140 data.iXferHeader.timestamp = iTimeStamp;
1141 data.iXferHeader.flags = 0;
1142 data.iXferHeader.duration = 0;
1143 data.iXferHeader.stream_id = 0;
1144 data.iFrameBuffer = frame;
1145 data.iFrameSize = size;
1146
1147 // lock mutex and queue frame buffer
1148 iFrameQueueMutex.Lock();
1149 iFrameQueue.push_back(data);
1150 iFrameQueueMutex.Unlock();
1151 RunIfNotReady();
1152
1153 return PVMFSuccess;
1154 }
1155
1156 // camera callback interface
postData(int32_t msgType,const sp<IMemory> & dataPtr)1157 void AndroidCameraInputListener::postData(int32_t msgType, const sp<IMemory>& dataPtr)
1158 {
1159 }
1160
postDataTimestamp(nsecs_t timestamp,int32_t msgType,const sp<IMemory> & dataPtr)1161 void AndroidCameraInputListener::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
1162 {
1163 if ((mCameraInput != NULL) && (msgType == CAMERA_MSG_VIDEO_FRAME)) {
1164 mCameraInput->postWriteAsync(timestamp, dataPtr);
1165 }
1166 }
1167
1168