Fix bug 5553055 support video only format change in MP2TS

Allow command data when enqueueing a format change command.
Support format change where the application signals that the
 change is for the video stream only. Consider any other change
 or format change command with invalid data as a full format
 change.

Change-Id: I6c684eab36a51dded7e3d7e72b8effe13dac6cc8
diff --git a/include/OMXAL/OpenMAXAL_Android.h b/include/OMXAL/OpenMAXAL_Android.h
index 10f36f4..34b9dd9 100644
--- a/include/OMXAL/OpenMAXAL_Android.h
+++ b/include/OMXAL/OpenMAXAL_Android.h
@@ -57,6 +57,13 @@
 #define XA_ANDROID_ITEMKEY_BUFFERQUEUEEVENT ((XAuint32) 0x00000003)
 #define XA_ANDROID_ITEMKEY_FORMAT_CHANGE    ((XAuint32) 0x00000004)
 
+// optional data for XA_ANDROID_ITEMKEY_FORMAT_CHANGE, used when only one stream changes format,
+//   and the others remain continuous (i.e. no temporal discontinuity is introduced for them)
+//   candidate for being exposed in NDK
+#define XA_ANDROID_FORMATCHANGE_ITEMDATA_VIDEO  ((XAuint32) 0x00000001)
+//   not supported at this stage, for illustration purposes only
+//#define XA_ANDROID_FORMATCHANGE_ITEMDATA_AUDIO ((XAuint32) 0x00000002)
+
 #define XA_ANDROIDBUFFERQUEUEEVENT_NONE        ((XAuint32) 0x00000000)
 #define XA_ANDROIDBUFFERQUEUEEVENT_PROCESSED   ((XAuint32) 0x00000001)
 #if 0   // reserved for future use
diff --git a/src/android/android_StreamPlayer.cpp b/src/android/android_StreamPlayer.cpp
index e2fa670..b87733c 100644
--- a/src/android/android_StreamPlayer.cpp
+++ b/src/android/android_StreamPlayer.cpp
@@ -159,17 +159,27 @@
                 msg->setInt64(IStreamListener::kKeyResumeAtPTS,
                         (int64_t)oldFront->mItems.mTsCmdData.mPts);
                 receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
-            } else if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_FORMAT_CHANGE) {
+            } else if (oldFront->mItems.mTsCmdData.mTsCmdCode
+                    & ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL) {
                 sp<AMessage> msg = new AMessage();
-                // positive value for format change key makes the discontinuity "hard", see key def
                 msg->setInt32(
                         IStreamListener::kKeyDiscontinuityMask,
                         ATSParser::DISCONTINUITY_FORMATCHANGE);
-
+                receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
+            } else if (oldFront->mItems.mTsCmdData.mTsCmdCode
+                    & ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO) {
+                sp<AMessage> msg = new AMessage();
+                msg->setInt32(
+                        IStreamListener::kKeyDiscontinuityMask,
+                        ATSParser::DISCONTINUITY_VIDEO_FORMAT);
                 receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
             }
+            // note that here we are intentionally only supporting
+            //   ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO, see IAndroidBufferQueue.c
+
+            // some commands may introduce a time discontinuity, reevaluate position if needed
             if (oldFront->mItems.mTsCmdData.mTsCmdCode & (ANDROID_MP2TSEVENT_DISCONTINUITY |
-                    ANDROID_MP2TSEVENT_DISCON_NEWPTS | ANDROID_MP2TSEVENT_FORMAT_CHANGE)) {
+                    ANDROID_MP2TSEVENT_DISCON_NEWPTS | ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL)) {
                 const sp<StreamPlayer> player(mPlayer.promote());
                 if (player != NULL) {
                     // FIXME see note at onSeek
diff --git a/src/android/android_defs.h b/src/android/android_defs.h
index 2332a73..3106b41 100644
--- a/src/android/android_defs.h
+++ b/src/android/android_defs.h
@@ -134,7 +134,8 @@
 // associated presentation time stamp
 #define ANDROID_MP2TSEVENT_DISCON_NEWPTS ((SLuint32) 0x1 << 2)
 // buffer marks a format change with previous TS data, resume display as soon as possible
-#define ANDROID_MP2TSEVENT_FORMAT_CHANGE ((SLuint32) 0x1 << 3)
+#define ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL  ((SLuint32) 0x1 << 3)
+#define ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO ((SLuint32) 0x1 << 4)
 
 /**
  * Event mask for AAC ADTS events associated with ADTS data
diff --git a/src/itf/IAndroidBufferQueue.c b/src/itf/IAndroidBufferQueue.c
index 278b7fd..884f637 100644
--- a/src/itf/IAndroidBufferQueue.c
+++ b/src/itf/IAndroidBufferQueue.c
@@ -119,10 +119,29 @@
                 break;
 
               case SL_ANDROID_ITEMKEY_FORMAT_CHANGE:
-                pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE;
-                if (pItems->itemSize != 0) {
-                    SL_LOGE("Invalid item parameter size %u for format change, ignoring value",
-                            pItems->itemSize);
+                // distinguish between a "full" format change and one where it says what changed
+                if (pItems->itemSize == 0) {
+                    SL_LOGV("Received format change with no data == full format change");
+                    pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
+                } else if (pItems->itemSize == sizeof(SLuint32)) {
+                    XAuint32 formatData = *((XAuint32*)pItems->itemData);
+                    // intentionally only supporting video change when reading which specific
+                    //    stream has changed, interpret other changes as full change
+                    if (formatData == XA_ANDROID_FORMATCHANGE_ITEMDATA_VIDEO) {
+                        pBuff->mItems.mTsCmdData.mTsCmdCode |=
+                                ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO;
+                        SL_LOGV("Received video format change");
+                    } else {
+                        // note that we don't support specifying
+                        //    ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL by having all bits of
+                        //    the data mask set, we default to it with unsupported masks
+                        SL_LOGE("Received format change with unsupported data, ignoring data");
+                        pBuff->mItems.mTsCmdData.mTsCmdCode |=
+                                ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
+                    }
+                } else {
+                    SL_LOGE("Received format change with invalid data size, ignoring data");
+                    pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
                 }
                 break;
 
@@ -178,7 +197,8 @@
           case ANDROID_MP2TSEVENT_EOS:
           case ANDROID_MP2TSEVENT_DISCONTINUITY:
           case ANDROID_MP2TSEVENT_DISCON_NEWPTS:
-          case ANDROID_MP2TSEVENT_FORMAT_CHANGE:
+          case ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL:
+          case ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO:
             break;
           // no combinations are allowed
           default: