• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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