Better organize media recorder error and information event and types

Change-Id: I45f1f953596985494725525c1fabf57eccc19175
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index a710546..67d940b 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -104,35 +104,62 @@
 };
 
 /*
- * The state machine of the media_recorder uses a set of different state names.
- * The mapping between the media_recorder and the pvauthorengine is shown below:
- *
- *    mediarecorder                        pvauthorengine
- * ----------------------------------------------------------------
- *    MEDIA_RECORDER_ERROR                 ERROR
- *    MEDIA_RECORDER_IDLE                  IDLE
- *    MEDIA_RECORDER_INITIALIZED           OPENED
- *    MEDIA_RECORDER_DATASOURCE_CONFIGURED
- *    MEDIA_RECORDER_PREPARED              INITIALIZED
- *    MEDIA_RECORDER_RECORDING             RECORDING
+ * The state machine of the media_recorder.
  */
 enum media_recorder_states {
+    // Error state.
     MEDIA_RECORDER_ERROR                 =      0,
+
+    // Recorder was just created.
     MEDIA_RECORDER_IDLE                  = 1 << 0,
+
+    // Recorder has been initialized.
     MEDIA_RECORDER_INITIALIZED           = 1 << 1,
+
+    // Configuration of the recorder has been completed.
     MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2,
+
+    // Recorder is ready to start.
     MEDIA_RECORDER_PREPARED              = 1 << 3,
+
+    // Recording is in progress.
     MEDIA_RECORDER_RECORDING             = 1 << 4,
 };
 
 // The "msg" code passed to the listener in notify.
 enum media_recorder_event_type {
+    MEDIA_RECORDER_EVENT_LIST_START               = 1,
     MEDIA_RECORDER_EVENT_ERROR                    = 1,
-    MEDIA_RECORDER_EVENT_INFO                     = 2
+    MEDIA_RECORDER_EVENT_INFO                     = 2,
+    MEDIA_RECORDER_EVENT_LIST_END                 = 99,
+
+    // Track related event types
+    MEDIA_RECORDER_TRACK_EVENT_LIST_START         = 100,
+    MEDIA_RECORDER_TRACK_EVENT_ERROR              = 100,
+    MEDIA_RECORDER_TRACK_EVENT_INFO               = 101,
+    MEDIA_RECORDER_TRACK_EVENT_LIST_END           = 1000,
 };
 
+/*
+ * The (part of) "what" code passed to the listener in notify.
+ * When the error or info type is track specific, the what has
+ * the following layout:
+ * the left-most 16-bit is meant for error or info type.
+ * the right-most 4-bit is meant for track id.
+ * the rest is reserved.
+ *
+ * | track id | reserved |     error or info type     |
+ * 31         28         16                           0
+ *
+ */
 enum media_recorder_error_type {
-    MEDIA_RECORDER_ERROR_UNKNOWN                  = 1
+    MEDIA_RECORDER_ERROR_UNKNOWN                   = 1,
+
+    // Track related error type
+    MEDIA_RECORDER_TRACK_ERROR_LIST_START          = 100,
+    MEDIA_RECORDER_TRACK_ERROR_GENERAL             = 100,
+    MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME       = 200,
+    MEDIA_RECORDER_TRACK_ERROR_LIST_END            = 1000,
 };
 
 // The codes are distributed as follow:
@@ -141,11 +168,15 @@
 //
 enum media_recorder_info_type {
     MEDIA_RECORDER_INFO_UNKNOWN                   = 1,
+
     MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800,
     MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED      = 801,
-    MEDIA_RECORDER_INFO_COMPLETION_STATUS         = 802,
-    MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS     = 803,
-    MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS      = 804,
+
+    // All track related informtional events start here
+    MEDIA_RECORDER_TRACK_INFO_LIST_START           = 1000,
+    MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS    = 1000,
+    MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME     = 1001,
+    MEDIA_RECORDER_TRACK_INFO_LIST_END             = 2000,
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 5c5229d..15f86ea 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -157,7 +157,7 @@
     bool use32BitFileOffset() const;
     bool exceedsFileDurationLimit();
     bool isFileStreamable() const;
-    void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
+    void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
     void writeCompositionMatrix(int32_t degrees);
 
     MPEG4Writer(const MPEG4Writer &);
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 0db3d1d..69846eb 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -269,7 +269,7 @@
     }
 
     if (stoppedPrematurely) {
-        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
     }
 
     close(mFd);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 5d6ea7c..edf76b5 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -52,7 +52,7 @@
 
 class MPEG4Writer::Track {
 public:
-    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
 
     ~Track();
 
@@ -82,6 +82,7 @@
     bool mIsAvc;
     bool mIsAudio;
     bool mIsMPEG4;
+    int32_t mTrackId;
     int64_t mTrackDurationUs;
 
     // For realtime applications, we need to adjust the media clock
@@ -295,7 +296,12 @@
 }
 
 status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
-    Track *track = new Track(this, source);
+    Mutex::Autolock l(mLock);
+    if (mStarted) {
+        LOGE("Attempt to add source AFTER recording is started");
+        return UNKNOWN_ERROR;
+    }
+    Track *track = new Track(this, source, mTracks.size());
     mTracks.push_back(track);
 
     return OK;
@@ -945,7 +951,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Writer::Track::Track(
-        MPEG4Writer *owner, const sp<MediaSource> &source)
+        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
     : mOwner(owner),
       mMeta(source->getFormat()),
       mSource(source),
@@ -953,6 +959,7 @@
       mPaused(false),
       mResumed(false),
       mStarted(false),
+      mTrackId(trackId),
       mTrackDurationUs(0),
       mEstimatedTrackSizeBytes(0),
       mSamplesHaveSameSize(true),
@@ -2030,7 +2037,7 @@
         (OK != checkCodecSpecificData())) {          // no codec specific data
         err = ERROR_MALFORMED;
     }
-    mOwner->trackProgressStatus(this, -1, err);
+    mOwner->trackProgressStatus(mTrackId, -1, err);
 
     // Last chunk
     if (mOwner->numTracks() == 1) {
@@ -2077,41 +2084,34 @@
     if (mTrackEveryTimeDurationUs > 0 &&
         timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
         LOGV("Fire time tracking progress status at %lld us", timeUs);
-        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
+        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
         mPreviousTrackTimeUs = timeUs;
     }
 }
 
 void MPEG4Writer::trackProgressStatus(
-        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
+        size_t trackId, int64_t timeUs, status_t err) {
     Mutex::Autolock lock(mLock);
-    int32_t nTracks = mTracks.size();
-    CHECK(nTracks >= 1);
-    CHECK(nTracks < 64);  // Arbitrary number
-
-    int32_t trackNum = 0;
-    CHECK(trackNum < nTracks);
-    trackNum <<= 16;
+    int32_t trackNum = (trackId << 28);
 
     // Error notification
     // Do not consider ERROR_END_OF_STREAM an error
     if (err != OK && err != ERROR_END_OF_STREAM) {
-        notify(MEDIA_RECORDER_EVENT_ERROR,
-               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
+        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
+               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
                err);
         return;
     }
 
     if (timeUs == -1) {
         // Send completion notification
-        notify(MEDIA_RECORDER_EVENT_INFO,
-               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
+        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
                err);
-        return;
     } else {
         // Send progress status
-        notify(MEDIA_RECORDER_EVENT_INFO,
-               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
+        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
                timeUs / 1000);
     }
 }