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