dom/camera/GonkCameraSource.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*
     2  * Copyright (C) 2009 The Android Open Source Project
     3  * Copyright (C) 2013 Mozilla Foundation
     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  */
    18 #include <base/basictypes.h>
    19 #include "nsDebug.h"
    20 #define DOM_CAMERA_LOG_LEVEL        3
    21 #include "CameraCommon.h"
    22 /*
    23 #define CS_LOGD(...) DOM_CAMERA_LOGA(__VA_ARGS__)
    24 #define CS_LOGV(...) DOM_CAMERA_LOGI(__VA_ARGS__)
    25 #define CS_LOGI(...) DOM_CAMERA_LOGI(__VA_ARGS__)
    26 #define CS_LOGW(...) DOM_CAMERA_LOGW(__VA_ARGS__)
    27 #define CS_LOGE(...) DOM_CAMERA_LOGE(__VA_ARGS__)
    28 */
    30 #define CS_LOGD(fmt, ...) DOM_CAMERA_LOGA("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    31 #define CS_LOGV(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    32 #define CS_LOGI(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    33 #define CS_LOGW(fmt, ...) DOM_CAMERA_LOGW("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    34 #define CS_LOGE(fmt, ...) DOM_CAMERA_LOGE("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
    36 #include <OMX_Component.h>
    37 #include <binder/IPCThreadState.h>
    38 #include <media/stagefright/foundation/ADebug.h>
    39 #include <media/stagefright/MediaDefs.h>
    40 #include <media/stagefright/MediaErrors.h>
    41 #include <media/stagefright/MetaData.h>
    42 #include <camera/CameraParameters.h>
    43 #include <utils/String8.h>
    44 #include <cutils/properties.h>
    46 #include "GonkCameraSource.h"
    47 #include "GonkCameraListener.h"
    48 #include "GonkCameraHwMgr.h"
    50 using namespace mozilla;
    52 namespace android {
    54 static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
    56 struct GonkCameraSourceListener : public GonkCameraListener {
    57     GonkCameraSourceListener(const sp<GonkCameraSource> &source);
    59     virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
    60     virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
    61                           camera_frame_metadata_t *metadata);
    63     virtual void postDataTimestamp(
    64             nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
    66 protected:
    67     virtual ~GonkCameraSourceListener();
    69 private:
    70     wp<GonkCameraSource> mSource;
    72     GonkCameraSourceListener(const GonkCameraSourceListener &);
    73     GonkCameraSourceListener &operator=(const GonkCameraSourceListener &);
    74 };
    76 GonkCameraSourceListener::GonkCameraSourceListener(const sp<GonkCameraSource> &source)
    77     : mSource(source) {
    78 }
    80 GonkCameraSourceListener::~GonkCameraSourceListener() {
    81 }
    83 void GonkCameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
    84     CS_LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
    85 }
    87 void GonkCameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
    88                                     camera_frame_metadata_t *metadata) {
    89     CS_LOGV("postData(%d, ptr:%p, size:%d)",
    90          msgType, dataPtr->pointer(), dataPtr->size());
    92     sp<GonkCameraSource> source = mSource.promote();
    93     if (source.get() != NULL) {
    94         source->dataCallback(msgType, dataPtr);
    95     }
    96 }
    98 void GonkCameraSourceListener::postDataTimestamp(
    99         nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
   101     sp<GonkCameraSource> source = mSource.promote();
   102     if (source.get() != NULL) {
   103         source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
   104     }
   105 }
   107 static int32_t getColorFormat(const char* colorFormat) {
   108     return OMX_COLOR_FormatYUV420SemiPlanar; //XXX nsGonkCameraControl uses only YUV420SemiPlanar
   110     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
   111        return OMX_COLOR_FormatYUV420Planar;
   112     }
   114     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
   115        return OMX_COLOR_FormatYUV422SemiPlanar;
   116     }
   118     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
   119         return OMX_COLOR_FormatYUV420SemiPlanar;
   120     }
   122     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
   123         return OMX_COLOR_FormatYCbYCr;
   124     }
   126     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
   127        return OMX_COLOR_Format16bitRGB565;
   128     }
   130     if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
   131        return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
   132     }
   133 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   134     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
   135         return OMX_COLOR_FormatAndroidOpaque;
   136     }
   137 #endif
   138     CS_LOGE("Uknown color format (%s), please add it to "
   139          "GonkCameraSource::getColorFormat", colorFormat);
   141     CHECK(!"Unknown color format");
   142 }
   144 GonkCameraSource *GonkCameraSource::Create(
   145     const sp<GonkCameraHardware>& aCameraHw,
   146     Size videoSize,
   147     int32_t frameRate,
   148     bool storeMetaDataInVideoBuffers) {
   150     GonkCameraSource *source = new GonkCameraSource(aCameraHw,
   151                     videoSize, frameRate,
   152                     storeMetaDataInVideoBuffers);
   153     return source;
   154 }
   156 GonkCameraSource::GonkCameraSource(
   157     const sp<GonkCameraHardware>& aCameraHw,
   158     Size videoSize,
   159     int32_t frameRate,
   160     bool storeMetaDataInVideoBuffers)
   161     : mCameraFlags(0),
   162       mNumInputBuffers(0),
   163       mVideoFrameRate(-1),
   164       mNumFramesReceived(0),
   165       mLastFrameTimestampUs(0),
   166       mStarted(false),
   167       mNumFramesEncoded(0),
   168       mTimeBetweenFrameCaptureUs(0),
   169       mFirstFrameTimeUs(0),
   170       mNumFramesDropped(0),
   171       mNumGlitches(0),
   172       mGlitchDurationThresholdUs(200000),
   173       mCollectStats(false),
   174       mCameraHw(aCameraHw) {
   175     mVideoSize.width  = -1;
   176     mVideoSize.height = -1;
   178     mInitCheck = init(
   179                     videoSize, frameRate,
   180                     storeMetaDataInVideoBuffers);
   181     if (mInitCheck != OK) releaseCamera();
   182 }
   184 status_t GonkCameraSource::initCheck() const {
   185     return mInitCheck;
   186 }
   188 //TODO: Do we need to reimplement isCameraAvailable?
   190 /*
   191  * Check to see whether the requested video width and height is one
   192  * of the supported sizes.
   193  * @param width the video frame width in pixels
   194  * @param height the video frame height in pixels
   195  * @param suppportedSizes the vector of sizes that we check against
   196  * @return true if the dimension (width and height) is supported.
   197  */
   198 static bool isVideoSizeSupported(
   199     int32_t width, int32_t height,
   200     const Vector<Size>& supportedSizes) {
   202     CS_LOGV("isVideoSizeSupported");
   203     for (size_t i = 0; i < supportedSizes.size(); ++i) {
   204         if (width  == supportedSizes[i].width &&
   205             height == supportedSizes[i].height) {
   206             return true;
   207         }
   208     }
   209     return false;
   210 }
   212 /*
   213  * If the preview and video output is separate, we only set the
   214  * the video size, and applications should set the preview size
   215  * to some proper value, and the recording framework will not
   216  * change the preview size; otherwise, if the video and preview
   217  * output is the same, we need to set the preview to be the same
   218  * as the requested video size.
   219  *
   220  */
   221 /*
   222  * Query the camera to retrieve the supported video frame sizes
   223  * and also to see whether CameraParameters::setVideoSize()
   224  * is supported or not.
   225  * @param params CameraParameters to retrieve the information
   226  * @@param isSetVideoSizeSupported retunrs whether method
   227  *      CameraParameters::setVideoSize() is supported or not.
   228  * @param sizes returns the vector of Size objects for the
   229  *      supported video frame sizes advertised by the camera.
   230  */
   231 static void getSupportedVideoSizes(
   232     const CameraParameters& params,
   233     bool *isSetVideoSizeSupported,
   234     Vector<Size>& sizes) {
   236     *isSetVideoSizeSupported = true;
   237     params.getSupportedVideoSizes(sizes);
   238     if (sizes.size() == 0) {
   239         CS_LOGD("Camera does not support setVideoSize()");
   240         params.getSupportedPreviewSizes(sizes);
   241         *isSetVideoSizeSupported = false;
   242     }
   243 }
   245 /*
   246  * Check whether the camera has the supported color format
   247  * @param params CameraParameters to retrieve the information
   248  * @return OK if no error.
   249  */
   250 status_t GonkCameraSource::isCameraColorFormatSupported(
   251         const CameraParameters& params) {
   252     mColorFormat = getColorFormat(params.get(
   253             CameraParameters::KEY_VIDEO_FRAME_FORMAT));
   254     if (mColorFormat == -1) {
   255         return BAD_VALUE;
   256     }
   257     return OK;
   258 }
   260 /*
   261  * Configure the camera to use the requested video size
   262  * (width and height) and/or frame rate. If both width and
   263  * height are -1, configuration on the video size is skipped.
   264  * if frameRate is -1, configuration on the frame rate
   265  * is skipped. Skipping the configuration allows one to
   266  * use the current camera setting without the need to
   267  * actually know the specific values (see Create() method).
   268  *
   269  * @param params the CameraParameters to be configured
   270  * @param width the target video frame width in pixels
   271  * @param height the target video frame height in pixels
   272  * @param frameRate the target frame rate in frames per second.
   273  * @return OK if no error.
   274  */
   275 status_t GonkCameraSource::configureCamera(
   276         CameraParameters* params,
   277         int32_t width, int32_t height,
   278         int32_t frameRate) {
   279     CS_LOGV("configureCamera");
   280     Vector<Size> sizes;
   281     bool isSetVideoSizeSupportedByCamera = true;
   282     getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
   283     bool isCameraParamChanged = false;
   284     if (width != -1 && height != -1) {
   285         if (!isVideoSizeSupported(width, height, sizes)) {
   286             CS_LOGE("Video dimension (%dx%d) is unsupported", width, height);
   287             return BAD_VALUE;
   288         }
   289         if (isSetVideoSizeSupportedByCamera) {
   290             params->setVideoSize(width, height);
   291         } else {
   292             params->setPreviewSize(width, height);
   293         }
   294         isCameraParamChanged = true;
   295     } else if ((width == -1 && height != -1) ||
   296                (width != -1 && height == -1)) {
   297         // If one and only one of the width and height is -1
   298         // we reject such a request.
   299         CS_LOGE("Requested video size (%dx%d) is not supported", width, height);
   300         return BAD_VALUE;
   301     } else {  // width == -1 && height == -1
   302         // Do not configure the camera.
   303         // Use the current width and height value setting from the camera.
   304     }
   306     if (frameRate != -1) {
   307         CHECK(frameRate > 0 && frameRate <= 120);
   308         const char* supportedFrameRates =
   309                 params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
   310         CHECK(supportedFrameRates != NULL);
   311         CS_LOGV("Supported frame rates: %s", supportedFrameRates);
   312         char buf[4];
   313         snprintf(buf, 4, "%d", frameRate);
   314         if (strstr(supportedFrameRates, buf) == NULL) {
   315             CS_LOGE("Requested frame rate (%d) is not supported: %s",
   316                 frameRate, supportedFrameRates);
   317             return BAD_VALUE;
   318         }
   320         // The frame rate is supported, set the camera to the requested value.
   321         params->setPreviewFrameRate(frameRate);
   322         isCameraParamChanged = true;
   323     } else {  // frameRate == -1
   324         // Do not configure the camera.
   325         // Use the current frame rate value setting from the camera
   326     }
   328     if (isCameraParamChanged) {
   329         // Either frame rate or frame size needs to be changed.
   330         if (OK != mCameraHw->PushParameters(*params)) {
   331             CS_LOGE("Could not change settings."
   332                  " Someone else is using camera?");
   333             return -EBUSY;
   334         }
   335     }
   336     return OK;
   337 }
   339 /*
   340  * Check whether the requested video frame size
   341  * has been successfully configured or not. If both width and height
   342  * are -1, check on the current width and height value setting
   343  * is performed.
   344  *
   345  * @param params CameraParameters to retrieve the information
   346  * @param the target video frame width in pixels to check against
   347  * @param the target video frame height in pixels to check against
   348  * @return OK if no error
   349  */
   350 status_t GonkCameraSource::checkVideoSize(
   351         const CameraParameters& params,
   352         int32_t width, int32_t height) {
   354     CS_LOGV("checkVideoSize");
   355     // The actual video size is the same as the preview size
   356     // if the camera hal does not support separate video and
   357     // preview output. In this case, we retrieve the video
   358     // size from preview.
   359     int32_t frameWidthActual = -1;
   360     int32_t frameHeightActual = -1;
   361     Vector<Size> sizes;
   362     params.getSupportedVideoSizes(sizes);
   363     if (sizes.size() == 0) {
   364         // video size is the same as preview size
   365         params.getPreviewSize(&frameWidthActual, &frameHeightActual);
   366     } else {
   367         // video size may not be the same as preview
   368         params.getVideoSize(&frameWidthActual, &frameHeightActual);
   369     }
   370     if (frameWidthActual < 0 || frameHeightActual < 0) {
   371         CS_LOGE("Failed to retrieve video frame size (%dx%d)",
   372                 frameWidthActual, frameHeightActual);
   373         return UNKNOWN_ERROR;
   374     }
   376     // Check the actual video frame size against the target/requested
   377     // video frame size.
   378     if (width != -1 && height != -1) {
   379         if (frameWidthActual != width || frameHeightActual != height) {
   380             CS_LOGE("Failed to set video frame size to %dx%d. "
   381                     "The actual video size is %dx%d ", width, height,
   382                     frameWidthActual, frameHeightActual);
   383             return UNKNOWN_ERROR;
   384         }
   385     }
   387     // Good now.
   388     mVideoSize.width = frameWidthActual;
   389     mVideoSize.height = frameHeightActual;
   390     return OK;
   391 }
   393 /*
   394  * Check the requested frame rate has been successfully configured or not.
   395  * If the target frameRate is -1, check on the current frame rate value
   396  * setting is performed.
   397  *
   398  * @param params CameraParameters to retrieve the information
   399  * @param the target video frame rate to check against
   400  * @return OK if no error.
   401  */
   402 status_t GonkCameraSource::checkFrameRate(
   403         const CameraParameters& params,
   404         int32_t frameRate) {
   406     CS_LOGV("checkFrameRate");
   407     int32_t frameRateActual = params.getPreviewFrameRate();
   408     if (frameRateActual < 0) {
   409         CS_LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
   410         return UNKNOWN_ERROR;
   411     }
   413     // Check the actual video frame rate against the target/requested
   414     // video frame rate.
   415     if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
   416         CS_LOGE("Failed to set preview frame rate to %d fps. The actual "
   417                 "frame rate is %d", frameRate, frameRateActual);
   418         return UNKNOWN_ERROR;
   419     }
   421     // Good now.
   422     mVideoFrameRate = frameRateActual;
   423     return OK;
   424 }
   426 /*
   427  * Initialize the GonkCameraSource so that it becomes
   428  * ready for providing the video input streams as requested.
   429  * @param camera the camera object used for the video source
   430  * @param cameraId if camera == 0, use camera with this id
   431  *      as the video source
   432  * @param videoSize the target video frame size. If both
   433  *      width and height in videoSize is -1, use the current
   434  *      width and heigth settings by the camera
   435  * @param frameRate the target frame rate in frames per second.
   436  *      if it is -1, use the current camera frame rate setting.
   437  * @param storeMetaDataInVideoBuffers request to store meta
   438  *      data or real YUV data in video buffers. Request to
   439  *      store meta data in video buffers may not be honored
   440  *      if the source does not support this feature.
   441  *
   442  * @return OK if no error.
   443  */
   444 status_t GonkCameraSource::init(
   445         Size videoSize,
   446         int32_t frameRate,
   447         bool storeMetaDataInVideoBuffers) {
   449     CS_LOGV("init");
   450     status_t err = OK;
   451     //TODO: need to do something here to check the sanity of camera
   453     CameraParameters params;
   454     mCameraHw->PullParameters(params);
   455     if ((err = isCameraColorFormatSupported(params)) != OK) {
   456         return err;
   457     }
   459     // Set the camera to use the requested video frame size
   460     // and/or frame rate.
   461     if ((err = configureCamera(&params,
   462                     videoSize.width, videoSize.height,
   463                     frameRate))) {
   464         return err;
   465     }
   467     // Check on video frame size and frame rate.
   468     CameraParameters newCameraParams;
   469     mCameraHw->PullParameters(newCameraParams);
   470     if ((err = checkVideoSize(newCameraParams,
   471                 videoSize.width, videoSize.height)) != OK) {
   472         return err;
   473     }
   474     if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
   475         return err;
   476     }
   478     // By default, do not store metadata in video buffers
   479     mIsMetaDataStoredInVideoBuffers = false;
   480     mCameraHw->StoreMetaDataInBuffers(false);
   481     if (storeMetaDataInVideoBuffers) {
   482         if (OK == mCameraHw->StoreMetaDataInBuffers(true)) {
   483             mIsMetaDataStoredInVideoBuffers = true;
   484         }
   485     }
   487     int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
   488     if (glitchDurationUs > mGlitchDurationThresholdUs) {
   489         mGlitchDurationThresholdUs = glitchDurationUs;
   490     }
   492     // XXX: query camera for the stride and slice height
   493     // when the capability becomes available.
   494     mMeta = new MetaData;
   495     mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
   496     mMeta->setInt32(kKeyColorFormat, mColorFormat);
   497     mMeta->setInt32(kKeyWidth,       mVideoSize.width);
   498     mMeta->setInt32(kKeyHeight,      mVideoSize.height);
   499     mMeta->setInt32(kKeyStride,      mVideoSize.width);
   500     mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
   501     mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
   502     return OK;
   503 }
   505 GonkCameraSource::~GonkCameraSource() {
   506     if (mStarted) {
   507         reset();
   508     } else if (mInitCheck == OK) {
   509         // Camera is initialized but because start() is never called,
   510         // the lock on Camera is never released(). This makes sure
   511         // Camera's lock is released in this case.
   512         // TODO: Don't think I need to do this
   513         releaseCamera();
   514     }
   515 }
   517 int GonkCameraSource::startCameraRecording() {
   518     CS_LOGV("startCameraRecording");
   519     return mCameraHw->StartRecording();
   520 }
   522 status_t GonkCameraSource::start(MetaData *meta) {
   523     int rv;
   525     CS_LOGV("start");
   526     CHECK(!mStarted);
   527     if (mInitCheck != OK) {
   528         CS_LOGE("GonkCameraSource is not initialized yet");
   529         return mInitCheck;
   530     }
   532     char value[PROPERTY_VALUE_MAX];
   533     if (property_get("media.stagefright.record-stats", value, NULL)
   534         && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
   535         mCollectStats = true;
   536     }
   538     mStartTimeUs = 0;
   539     mNumInputBuffers = 0;
   540     if (meta) {
   541         int64_t startTimeUs;
   542         if (meta->findInt64(kKeyTime, &startTimeUs)) {
   543             mStartTimeUs = startTimeUs;
   544         }
   545 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   546         int32_t nBuffers;
   547         if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
   548             CHECK_GT(nBuffers, 0);
   549             mNumInputBuffers = nBuffers;
   550         }
   551 #endif
   552     }
   554     // Register a listener with GonkCameraHardware so that we can get callbacks
   555     mCameraHw->SetListener(new GonkCameraSourceListener(this));
   557     rv = startCameraRecording();
   559     mStarted = (rv == OK);
   560     return rv;
   561 }
   563 void GonkCameraSource::stopCameraRecording() {
   564     CS_LOGV("stopCameraRecording");
   565     mCameraHw->StopRecording();
   566 }
   568 void GonkCameraSource::releaseCamera() {
   569     CS_LOGV("releaseCamera");
   570 }
   572 status_t GonkCameraSource::reset() {
   573     CS_LOGD("reset: E");
   574     Mutex::Autolock autoLock(mLock);
   575     mStarted = false;
   576     mFrameAvailableCondition.signal();
   578     releaseQueuedFrames();
   579     while (!mFramesBeingEncoded.empty()) {
   580         if (NO_ERROR !=
   581             mFrameCompleteCondition.waitRelative(mLock,
   582                     mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
   583             CS_LOGW("Timed out waiting for outstanding frames being encoded: %d",
   584                 mFramesBeingEncoded.size());
   585         }
   586     }
   587     stopCameraRecording();
   588     releaseCamera();
   590     if (mCollectStats) {
   591         CS_LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
   592                 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
   593                 mLastFrameTimestampUs - mFirstFrameTimeUs);
   594     }
   596     if (mNumGlitches > 0) {
   597         CS_LOGW("%d long delays between neighboring video frames", mNumGlitches);
   598     }
   600     CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
   601     CS_LOGD("reset: X");
   602     return OK;
   603 }
   605 void GonkCameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
   606     CS_LOGV("releaseRecordingFrame");
   607     mCameraHw->ReleaseRecordingFrame(frame);
   608 }
   610 void GonkCameraSource::releaseQueuedFrames() {
   611     List<sp<IMemory> >::iterator it;
   612     while (!mFramesReceived.empty()) {
   613         it = mFramesReceived.begin();
   614         releaseRecordingFrame(*it);
   615         mFramesReceived.erase(it);
   616         ++mNumFramesDropped;
   617     }
   618 }
   620 sp<MetaData> GonkCameraSource::getFormat() {
   621     return mMeta;
   622 }
   624 void GonkCameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
   625     releaseRecordingFrame(frame);
   626 }
   628 void GonkCameraSource::signalBufferReturned(MediaBuffer *buffer) {
   629     CS_LOGV("signalBufferReturned: %p", buffer->data());
   630     Mutex::Autolock autoLock(mLock);
   631     for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
   632          it != mFramesBeingEncoded.end(); ++it) {
   633         if ((*it)->pointer() ==  buffer->data()) {
   634             releaseOneRecordingFrame((*it));
   635             mFramesBeingEncoded.erase(it);
   636             ++mNumFramesEncoded;
   637             buffer->setObserver(0);
   638             buffer->release();
   639             mFrameCompleteCondition.signal();
   640             return;
   641         }
   642     }
   643     CHECK(!"signalBufferReturned: bogus buffer");
   644 }
   646 status_t GonkCameraSource::read(
   647         MediaBuffer **buffer, const ReadOptions *options) {
   648     CS_LOGV("read");
   650     *buffer = NULL;
   652     int64_t seekTimeUs;
   653     ReadOptions::SeekMode mode;
   654     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
   655         return ERROR_UNSUPPORTED;
   656     }
   658     sp<IMemory> frame;
   659     int64_t frameTime;
   661     {
   662         Mutex::Autolock autoLock(mLock);
   663         while (mStarted && mFramesReceived.empty()) {
   664             if (NO_ERROR !=
   665                 mFrameAvailableCondition.waitRelative(mLock,
   666                     mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
   667                 //TODO: check sanity of camera?
   668                 CS_LOGW("Timed out waiting for incoming camera video frames: %lld us",
   669                     mLastFrameTimestampUs);
   670             }
   671         }
   672         if (!mStarted) {
   673             return OK;
   674         }
   675         frame = *mFramesReceived.begin();
   676         mFramesReceived.erase(mFramesReceived.begin());
   678         frameTime = *mFrameTimes.begin();
   679         mFrameTimes.erase(mFrameTimes.begin());
   680         mFramesBeingEncoded.push_back(frame);
   681         *buffer = new MediaBuffer(frame->pointer(), frame->size());
   682         (*buffer)->setObserver(this);
   683         (*buffer)->add_ref();
   684         (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
   685     }
   686     return OK;
   687 }
   689 void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs,
   690         int32_t msgType, const sp<IMemory> &data) {
   691     CS_LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
   692     Mutex::Autolock autoLock(mLock);
   693     if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
   694         CS_LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
   695         releaseOneRecordingFrame(data);
   696         return;
   697     }
   699     if (mNumFramesReceived > 0) {
   700         CHECK(timestampUs > mLastFrameTimestampUs);
   701         if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
   702             ++mNumGlitches;
   703         }
   704     }
   706     // May need to skip frame or modify timestamp. Currently implemented
   707     // by the subclass CameraSourceTimeLapse.
   708     if (skipCurrentFrame(timestampUs)) {
   709         releaseOneRecordingFrame(data);
   710         return;
   711     }
   713     mLastFrameTimestampUs = timestampUs;
   714     if (mNumFramesReceived == 0) {
   715         mFirstFrameTimeUs = timestampUs;
   716         // Initial delay
   717         if (mStartTimeUs > 0) {
   718             if (timestampUs < mStartTimeUs) {
   719                 // Frame was captured before recording was started
   720                 // Drop it without updating the statistical data.
   721                 releaseOneRecordingFrame(data);
   722                 return;
   723             }
   724             mStartTimeUs = timestampUs - mStartTimeUs;
   725         }
   726     }
   727     ++mNumFramesReceived;
   729     CHECK(data != NULL && data->size() > 0);
   730     mFramesReceived.push_back(data);
   731     int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
   732     mFrameTimes.push_back(timeUs);
   733     CS_LOGV("initial delay: %lld, current time stamp: %lld",
   734         mStartTimeUs, timeUs);
   735     mFrameAvailableCondition.signal();
   736 }
   738 bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {
   739     CS_LOGV("isMetaDataStoredInVideoBuffers");
   740     return mIsMetaDataStoredInVideoBuffers;
   741 }
   743 }  // namespace android

mercurial