Merge "Native input event dispatching." into gingerbread
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 24ac82b..cfc17a5 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,7 +24,7 @@
 
 class ISurface;
 class ICamera;
-class IMediaPlayerClient;
+class IMediaRecorderClient;
 
 class IMediaRecorder: public IInterface
 {
@@ -43,7 +43,7 @@
     virtual	status_t		setVideoSize(int width, int height) = 0;
     virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
     virtual     status_t                setParameters(const String8& params) = 0;
-    virtual     status_t                setListener(const sp<IMediaPlayerClient>& listener) = 0;
+    virtual     status_t                setListener(const sp<IMediaRecorderClient>& listener) = 0;
     virtual	status_t		prepare() = 0;
     virtual	status_t		getMaxAmplitude(int* max) = 0;
     virtual	status_t		start() = 0;
diff --git a/include/media/IMediaRecorderClient.h b/include/media/IMediaRecorderClient.h
new file mode 100644
index 0000000..0058ef2
--- /dev/null
+++ b/include/media/IMediaRecorderClient.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IMEDIARECORDERCLIENT_H
+#define ANDROID_IMEDIARECORDERCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMediaRecorderClient: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaRecorderClient);
+
+    virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaRecorderClient: public BnInterface<IMediaRecorderClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIARECORDERCLIENT_H
+
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5b787a7..497965c 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -41,7 +41,7 @@
     virtual status_t setOutputFile(const char *path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
     virtual status_t setParameters(const String8& params) = 0;
-    virtual status_t setListener(const sp<IMediaPlayerClient>& listener) = 0;
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
     virtual status_t prepare() = 0;
     virtual status_t start() = 0;
     virtual status_t stop() = 0;
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
index 4f17c1a..c04105e 100644
--- a/include/media/PVMediaRecorder.h
+++ b/include/media/PVMediaRecorder.h
@@ -18,7 +18,7 @@
 #ifndef ANDROID_PVMEDIARECORDER_H
 #define ANDROID_PVMEDIARECORDER_H
 
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 #include <media/MediaRecorderBase.h>
 
 namespace android {
@@ -45,7 +45,7 @@
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
-    virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t prepare();
     virtual status_t start();
     virtual status_t stop();
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 4f4ec43..b21bc4d 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -22,7 +22,7 @@
 #include <utils/threads.h>
 #include <utils/List.h>
 #include <utils/Errors.h>
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 #include <media/IMediaDeathNotifier.h>
 
 namespace android {
@@ -149,7 +149,7 @@
     virtual void notify(int msg, int ext1, int ext2) = 0;
 };
 
-class MediaRecorder : public BnMediaPlayerClient,
+class MediaRecorder : public BnMediaRecorderClient,
                       public virtual IMediaDeathNotifier
 {
 public:
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index 46aaf7c..e91d066 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -19,7 +19,7 @@
 #define MEDIA_WRITER_H_
 
 #include <utils/RefBase.h>
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 
 namespace android {
 
@@ -36,7 +36,7 @@
     virtual void pause() = 0;
     virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
     virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; }
-    virtual void setListener(const sp<IMediaPlayerClient>& listener) {
+    virtual void setListener(const sp<IMediaRecorderClient>& listener) {
         mListener = listener;
     }
 
@@ -44,7 +44,7 @@
     virtual ~MediaWriter() {}
     int64_t mMaxFileSizeLimitBytes;
     int64_t mMaxFileDurationLimitUs;
-    sp<IMediaPlayerClient> mListener;
+    sp<IMediaRecorderClient> mListener;
 
     void notify(int msg, int ext1, int ext2) {
         if (mListener != NULL) {
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 7908f5d..de9e51d 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -12,6 +12,7 @@
     mediaplayer.cpp \
     IMediaPlayerService.cpp \
     IMediaPlayerClient.cpp \
+    IMediaRecorderClient.cpp \
     IMediaPlayer.cpp \
     IMediaRecorder.cpp \
     Metadata.cpp \
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 2bc2a7e..9fe207c 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -21,7 +21,7 @@
 #include <binder/Parcel.h>
 #include <surfaceflinger/ISurface.h>
 #include <camera/ICamera.h>
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 #include <media/IMediaRecorder.h>
 
 namespace android {
@@ -189,7 +189,7 @@
         return reply.readInt32();
     }
 
-    status_t setListener(const sp<IMediaPlayerClient>& listener)
+    status_t setListener(const sp<IMediaRecorderClient>& listener)
     {
         LOGV("setListener(%p)", listener.get());
         Parcel data, reply;
@@ -399,8 +399,8 @@
         case SET_LISTENER: {
             LOGV("SET_LISTENER");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
-            sp<IMediaPlayerClient> listener =
-                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+            sp<IMediaRecorderClient> listener =
+                interface_cast<IMediaRecorderClient>(data.readStrongBinder());
             reply->writeInt32(setListener(listener));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IMediaRecorderClient.cpp b/media/libmedia/IMediaRecorderClient.cpp
new file mode 100644
index 0000000..ff235c9
--- /dev/null
+++ b/media/libmedia/IMediaRecorderClient.cpp
@@ -0,0 +1,70 @@
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <media/IMediaRecorderClient.h>
+
+namespace android {
+
+enum {
+    NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpMediaRecorderClient: public BpInterface<IMediaRecorderClient>
+{
+public:
+    BpMediaRecorderClient(const sp<IBinder>& impl)
+        : BpInterface<IMediaRecorderClient>(impl)
+    {
+    }
+
+    virtual void notify(int msg, int ext1, int ext2)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
+        data.writeInt32(msg);
+        data.writeInt32(ext1);
+        data.writeInt32(ext2);
+        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaRecorderClient, "android.media.IMediaRecorderClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaRecorderClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case NOTIFY: {
+            CHECK_INTERFACE(IMediaRecorderClient, data, reply);
+            int msg = data.readInt32();
+            int ext1 = data.readInt32();
+            int ext2 = data.readInt32();
+            notify(msg, ext1, ext2);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 084f039..80b1cfd 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -318,7 +318,7 @@
     release();
 }
 
-status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener)
+status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
 {
     LOGV("setListener");
     Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index e07306b..b53d950 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -40,7 +40,7 @@
     virtual     status_t        setVideoSize(int width, int height);
     virtual     status_t        setVideoFrameRate(int frames_per_second);
     virtual     status_t        setParameters(const String8& params);
-    virtual     status_t        setListener(const sp<IMediaPlayerClient>& listener);
+    virtual     status_t        setListener(const sp<IMediaRecorderClient>& listener);
     virtual     status_t        prepare();
     virtual     status_t        getMaxAmplitude(int* max);
     virtual     status_t        start();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 1e20f7e..c4aeec3 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -456,7 +456,7 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) {
+status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
     mListener = listener;
 
     return OK;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 9fb7e8f..f4488b6 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -46,7 +46,7 @@
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
-    virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t prepare();
     virtual status_t start();
     virtual status_t pause();
@@ -63,7 +63,7 @@
 
     sp<Camera> mCamera;
     sp<ISurface> mPreviewSurface;
-    sp<IMediaPlayerClient> mListener;
+    sp<IMediaRecorderClient> mListener;
     sp<MediaWriter> mWriter;
     sp<AudioSource> mAudioSourceNode;
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index b3e1a01..a52c888 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -115,12 +115,17 @@
     status_t makeAVCCodecSpecificData(
             const uint8_t *data, size_t size);
     void writeOneChunk(bool isAvc);
-    void logStatisticalData(bool isAudio);
-    void findMinMaxFrameRates(float *minFps, float *maxFps);
-    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
+
+    // Track authoring progress status
     void trackProgressStatus(int32_t nFrames, int64_t timeUs);
     void initTrackingProgressStatus(MetaData *params);
 
+    // Utilities for collecting statistical data
+    void logStatisticalData(bool isAudio);
+    void findMinAvgMaxSampleDurationMs(
+            int32_t *min, int32_t *avg, int32_t *max);
+    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
+
     Track(const Track &);
     Track &operator=(const Track &);
 };
@@ -1184,14 +1189,16 @@
 
 void MPEG4Writer::Track::trackProgressStatus(int32_t nFrames, int64_t timeUs) {
     LOGV("trackProgressStatus: %d frames and %lld us", nFrames, timeUs);
-    if (nFrames % mTrackEveryNumberOfFrames == 0) {
+    if (mTrackEveryNumberOfFrames > 0 &&
+        nFrames % mTrackEveryNumberOfFrames == 0) {
         LOGV("Fire frame tracking progress status at frame %d", nFrames);
         mOwner->notify(MEDIA_RECORDER_EVENT_INFO,
                        MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS,
                        nFrames);
     }
 
-    if (timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
+    if (mTrackEveryTimeDurationUs > 0 &&
+        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
         LOGV("Fire time tracking progress status at %lld us", timeUs);
         mOwner->notify(MEDIA_RECORDER_EVENT_INFO,
                        MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
@@ -1200,21 +1207,28 @@
     }
 }
 
-void MPEG4Writer::Track::findMinMaxFrameRates(float *minFps, float *maxFps) {
-    int32_t minSampleDuration = 0x7FFFFFFF;
-    int32_t maxSampleDuration = 0;
+void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
+        int32_t *min, int32_t *avg, int32_t *max) {
+    CHECK(!mSampleInfos.empty());
+    int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000/ mSampleInfos.size();
+    int32_t minSampleDurationMs = 0x7FFFFFFF;
+    int32_t maxSampleDurationMs = 0;
     for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
         it != mSttsTableEntries.end(); ++it) {
-        int32_t sampleDuration = static_cast<int32_t>(it->sampleDuration);
-        if (sampleDuration > maxSampleDuration) {
-            maxSampleDuration = sampleDuration;
-        } else if (sampleDuration < minSampleDuration) {
-            minSampleDuration = sampleDuration;
+        int32_t sampleDurationMs = static_cast<int32_t>(it->sampleDuration);
+        if (sampleDurationMs > maxSampleDurationMs) {
+            maxSampleDurationMs = sampleDurationMs;
+        } else if (sampleDurationMs < minSampleDurationMs) {
+            minSampleDurationMs = sampleDurationMs;
         }
+        LOGI("sample duration: %d ms", sampleDurationMs);
     }
-    CHECK(minSampleDuration != 0 && maxSampleDuration != 0);
-    *minFps = 1000.0 / maxSampleDuration;
-    *maxFps = 1000.0 / minSampleDuration;
+    CHECK(minSampleDurationMs != 0);
+    CHECK(avgSampleDurationMs != 0);
+    CHECK(maxSampleDurationMs != 0);
+    *min = minSampleDurationMs;
+    *avg = avgSampleDurationMs;
+    *max = maxSampleDurationMs;
 }
 
 // Don't count the last duration
@@ -1250,16 +1264,18 @@
     }
 
     if (collectStats) {
-        if (isAudio) {
-            LOGI("audio track - duration %lld us", mMaxTimeStampUs);
-        } else {
-            float fps = (mSampleInfos.size() * 1000000.0) / mMaxTimeStampUs;
-            float minFps;
-            float maxFps;
-            findMinMaxFrameRates(&minFps, &maxFps);
-            LOGI("video track - duration %lld us", mMaxTimeStampUs);
+        LOGI("%s track - duration %lld us, total %d frames",
+                isAudio? "audio": "video", mMaxTimeStampUs,
+                mSampleInfos.size());
+        int32_t min, avg, max;
+        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
+        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
+        if (!isAudio) {
+            float avgFps = 1000.0 / avg;
+            float minFps = 1000.0 / max;
+            float maxFps = 1000.0 / min;
             LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
-                minFps, fps, maxFps);
+                minFps, avgFps, maxFps);
         }
 
         int64_t totalBytes = 0;