[R44c][ASF Parser] BZ193214 fix and review comments for ASF parser

BZ: 193214

This patch covers fix for BZ193214 and all review comments
incorporated in main branch patch 189154 (patchset 7).

Change-Id: Ic94fd907d924e7cc16483e93f649054d34a0d457
Signed-off-by: RupaliX <rupalix.sharma@intel.com>
Signed-off-by: Sudheer Mogilappagari <sudheer.mogilappagari@intel.com>
diff --git a/asfparser/AsfDataParser.cpp b/asfparser/AsfDataParser.cpp
index 3bd4d32..03e474d 100644
--- a/asfparser/AsfDataParser.cpp
+++ b/asfparser/AsfDataParser.cpp
@@ -24,6 +24,8 @@
 
 
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AsfDataParser"
 #include "AsfDataParser.h"
 #include "AsfGuids.h"
 #include "AsfObjects.h"
@@ -187,7 +189,6 @@
 
 int AsfSinglePayloadUncompressed::parse(uint8_t *buffer, uint32_t size, AsfPayloadDataInfo **out) {
     // initialize output
-    int retVal = 0;
     *out = NULL;
     streamNumber.value = *buffer;
     blockSize = 1;
@@ -221,8 +222,6 @@
         return ASF_PARSER_NO_MEMORY;
     }
 
-    ALOGD("replicatedDataLength = %d", replicatedDataLength);
-
     // point to replicated data into object's buffer. Yet to be interpreted.
     obj->replicatedDataLength = replicatedDataLength;
     obj->replicatedData = buffer + blockSize;
@@ -233,29 +232,16 @@
 
     blockSize += replicatedDataLength;
 
-    // defined for temporary use as arg for getPayloadExtensionSystems
-    uint8_t streamnumber = streamNumber.bits.streamNumber;
-    vector<PayloadExtensionSystem *> *extSystems;
-    retVal = AsfDataParser::mHeaderParser->getPayloadExtensionSystems(streamnumber, &extSystems);
-    if (retVal != ASF_PARSER_SUCCESS) {
-        ALOGD("Error while parsing Payload Extension Systems");
-    } else {
-        ALOGD("Extension System count = %d", extSystems->size());
-        // find IV in replicated data
-        int replicatedDataOffset = 0;
+    uint8_t streamNum = streamNumber.bits.streamNumber;
 
-        for (int i = 0; i < extSystems->size(); i++) {
-            // ptr to ext system's data in replicated data buffer.
-            if ((extSystems->at(i)->extensionSystemId) == ASF_Payload_Extension_System_Encryption_Sample_ID) {
-                obj->sampleID = obj->replicatedData + 8 + replicatedDataOffset;
-                obj->sampleIDLen = extSystems->at(i)->extensionDataSize;
-            }
-            if (extSystems->at(i)->extensionDataSize == 0xFFFF) {
-                uint16_t nSize = *((uint16_t*) (obj->replicatedData + 8 + replicatedDataOffset));
-                replicatedDataOffset += (sizeof(uint16_t) + nSize);
-            } else {
-                replicatedDataOffset += extSystems->at(i)->extensionDataSize;
-            }
+    // Extension Systems are required if replicatedDataLength is greater than 8.
+    if (replicatedDataLength > 8) {
+        // For protected content, get SampleID which is used as IV.
+        int returnStatus = AsfDataParser::mHeaderParser->parseSampleIDFromReplicatedData(obj,streamNum);
+        if (returnStatus == ASF_PARSER_UNEXPECTED_VALUE) {
+            ALOGD("Only Encryption_Sample_ID extension system is supported");
+        } else if (returnStatus != ASF_PARSER_SUCCESS) {
+            return ASF_PARSER_FAILED;
         }
     }
 
@@ -376,7 +362,6 @@
 
 int AsfMultiplePayloadsUncompressed::parse(uint8_t *buffer, uint32_t size, AsfPayloadDataInfo **out) {
     // initialize output
-    int retVal = 0;
     *out = NULL;
     streamNumber.value = *buffer;
     blockSize = 1;
@@ -410,8 +395,6 @@
         return ASF_PARSER_NO_MEMORY;
     }
 
-    ALOGD("replicatedDataLength = %d", replicatedDataLength);
-
     // point to replicated data into object's buffer. Yet to be interpreted.
     obj->replicatedDataLength = replicatedDataLength;
     obj->replicatedData = buffer + blockSize;
@@ -422,27 +405,17 @@
 
     blockSize += replicatedDataLength;
 
-    // defined for temporary use as arg for getPayloadExtensionSystems
-    uint8_t streamnumber = streamNumber.bits.streamNumber;
-    vector<PayloadExtensionSystem *> *extSystems;
-    retVal = AsfDataParser::mHeaderParser->getPayloadExtensionSystems(streamnumber, &extSystems);
-    if (retVal != ASF_PARSER_SUCCESS) {
-        ALOGD("Error while parsing Payload Extension Systems");
-    } else {
-        // find IV in replicated data
-        int replicatedDataOffset = 0;
-        for (int i = 0; i < extSystems->size(); i++) {
-            // ptr to ext system's data in replicated data buffer.
-            if ((extSystems->at(i)->extensionSystemId) == ASF_Payload_Extension_System_Encryption_Sample_ID) {
-                obj->sampleID = obj->replicatedData + 8 + replicatedDataOffset;
-                obj->sampleIDLen = extSystems->at(i)->extensionDataSize;
-            }
-            if (extSystems->at(i)->extensionDataSize == 0xFFFF) {
-                uint16_t nSize = *((uint16_t*) (obj->replicatedData + 8 + replicatedDataOffset));
-                replicatedDataOffset += (sizeof(uint16_t) + nSize);
-            } else {
-                replicatedDataOffset += extSystems->at(i)->extensionDataSize;
-            }
+    uint8_t streamNum = streamNumber.bits.streamNumber;
+
+    // Extension Systems are required if replicatedDataLength is greater than 8.
+    if (replicatedDataLength > 8) {
+        // For protected content, get SampleID which is used as IV.
+        int returnStatus = AsfDataParser::mHeaderParser->parseSampleIDFromReplicatedData(obj,streamNum);
+
+        if (returnStatus == ASF_PARSER_UNEXPECTED_VALUE) {
+            ALOGD("Only Encryption_Sample_ID extension system is supported");
+        } else if (returnStatus != ASF_PARSER_SUCCESS) {
+            return ASF_PARSER_FAILED;
         }
     }
 
diff --git a/asfparser/AsfHeaderParser.cpp b/asfparser/AsfHeaderParser.cpp
index 0d9b45e..4887a53 100644
--- a/asfparser/AsfHeaderParser.cpp
+++ b/asfparser/AsfHeaderParser.cpp
@@ -24,7 +24,7 @@
 
 
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "AsfHeaderParser"
 #include <utils/Log.h>
 
@@ -33,6 +33,7 @@
 
 #include <media/stagefright/Utils.h>
 
+#define PRFORMATTAG 0x5052
 AsfHeaderParser::AsfHeaderParser(void)
     : mAudioInfo(NULL),
       mVideoInfo(NULL),
@@ -54,18 +55,24 @@
     }
 
     // Deleting memory from mExtendedStreamPropertiesObj recursively
-    for (vector<AsfExtendedStreamPropertiesObject *>::iterator it = mExtendedStreamPropertiesObj.begin(); it != mExtendedStreamPropertiesObj.end(); ++it) {
+    for (vector<AsfExtendedStreamPropertiesExObject *>::iterator it = mExtendedStreamPropertiesObj.begin(); it != mExtendedStreamPropertiesObj.end(); ++it) {
+
+        for (int i = 0; i < (*it)->streamNames.size(); i++) {
+            if ((*it)->streamNames[i]->pStreamName != NULL) {
+                delete (*it)->streamNames[i]->pStreamName;
+            }
+            delete (*it)->streamNames[i];
+        }
+        (*it)->streamNames.clear();
+
         for (int i = 0; i < (*it)->extensionSystems.size(); i++) {
             if ((*it)->extensionSystems[i]->extensionSystemInfo != NULL) {
                 delete (*it)->extensionSystems[i]->extensionSystemInfo;
-                (*it)->extensionSystems[i]->extensionSystemInfo = NULL;
             }
             delete (*it)->extensionSystems[i];
-            (*it)->extensionSystems[i] = NULL;
         }
         (*it)->extensionSystems.clear();
         delete (*it);
-        (*it) = NULL;
     }
     mExtendedStreamPropertiesObj.clear();
 
@@ -177,30 +184,55 @@
             } else if(obj->objectID == ASF_Protection_System_Identifier_Object) {
                 mIsProtected = true;
                 LOGV("ASF_Protection_System_Identifier_Object");
-                uint64_t playreadyObjSize = obj->objectSize;
-                PlayreadyHeaderObj *plrdyHdrObj = (PlayreadyHeaderObj*)buffer;
+                if (obj->objectSize < sizeof(AsfProtectionSystemIdObj)) {
+                    LOGE("Unsupported Protection System Object");
+                    return ASF_PARSER_BAD_DATA;
+                }
+                AsfProtectionSystemIdObj *protectionSysObj = (AsfProtectionSystemIdObj*)buffer;
 
                 uint8_t* playreadyObjBuf = NULL;
-                GUID *pldyUuid = (GUID*)plrdyHdrObj->sysId;
-                memcpy(mPlayreadyUuid, (uint8_t*)pldyUuid, UUIDSIZE);
+                memcpy(mPlayreadyUuid, protectionSysObj->sysId, UUIDSIZE);
 
                 // Rights Management Header - Record Type = 0x0001
                 // Traverse till field containing number of records
-                playreadyObjBuf = buffer + sizeof(PlayreadyHeaderObj);
-                for (int i = 0; i < plrdyHdrObj->countRecords; i++) {
-                    uint16_t* recordType = (uint16_t*)playreadyObjBuf;
-                    if (*recordType == 0x01)  {// Rights management Header
-                        playreadyObjBuf += sizeof(uint16_t);
-                        uint16_t* recordLen = (uint16_t*)playreadyObjBuf;
-                        mPlayreadyHeaderLen = *recordLen;
+                playreadyObjBuf = buffer + sizeof(AsfProtectionSystemIdObj);
+                uint32_t sizeLeft = obj->objectSize - sizeof(AsfProtectionSystemIdObj); // For Maintaining and checking the left memory in the object
 
-                        mPlayreadyHeader = new uint8_t [mPlayreadyHeaderLen];
-                        if (mPlayreadyHeader == NULL) {
-                            return ASF_PARSER_NO_MEMORY;
-                        }
+                for (int i = 0; i < protectionSysObj->countRecords; i++) {
+                    if (sizeLeft > 4) {
+                        uint16_t recordType = *((uint16_t*)playreadyObjBuf);
                         playreadyObjBuf += sizeof(uint16_t);
-                        memcpy(mPlayreadyHeader, playreadyObjBuf, mPlayreadyHeaderLen);
-                        break;
+                        sizeLeft -= sizeof (recordType);
+
+                        uint16_t recordLen = *((uint16_t*)playreadyObjBuf);
+                        playreadyObjBuf += sizeof(uint16_t);
+                        sizeLeft -= sizeof (recordLen);
+                        if (sizeLeft < recordLen) {
+                            LOGE("Invalid Rec Protection Identifier Object");
+                            status = ASF_PARSER_BAD_DATA;
+                            break;
+                        }
+
+                        if (recordType == 0x01)  {// Rights management Header
+                            mPlayreadyHeaderLen = recordLen;
+
+                            if (mPlayreadyHeaderLen == 0) {
+                                LOGE("Invalid Protection System Record Length Value");
+                                return ASF_PARSER_BAD_DATA;
+                            }
+                            mPlayreadyHeader = new uint8_t [mPlayreadyHeaderLen];
+                            if (mPlayreadyHeader == NULL) {
+                                return ASF_PARSER_NO_MEMORY;
+                            }
+
+                            memcpy(mPlayreadyHeader, playreadyObjBuf, mPlayreadyHeaderLen);
+                            break;
+                        }
+                        playreadyObjBuf += recordLen;
+                        sizeLeft -= recordLen;
+                    } else {
+                        LOGE("Invalid sizeLeft");
+                        return ASF_PARSER_BAD_DATA;
                     }
                 }
             }
@@ -220,22 +252,26 @@
     return status;
 }
 
-int AsfHeaderParser::getPlayreadyUuid(uint8_t *playreadyUuid) {
-
+int AsfHeaderParser::getPlayreadyUuid(uint8_t playreadyUuid[], uint16_t len) {
     if (playreadyUuid == NULL || (!mIsProtected))
         return ASF_PARSER_FAILED;
+    if (len < UUIDSIZE) {
+        LOGE("Invalid length ");
+        return ASF_PARSER_FAILED;
+    }
+
     memcpy(playreadyUuid, mPlayreadyUuid, UUIDSIZE);
     return ASF_PARSER_SUCCESS;
 }
 
-int AsfHeaderParser::getPlayreadyHeaderXml(uint8_t *playreadyHeader, uint32_t *playreadyHeaderLen) {
+int AsfHeaderParser::getPlayreadyHeaderXml(uint8_t *header, uint32_t *len) {
 
-    if (playreadyHeader == NULL) {
-        *playreadyHeaderLen = mPlayreadyHeaderLen;
+    if (header == NULL) {
+        *len = mPlayreadyHeaderLen;
         return ASF_PARSER_NULL_POINTER;
     }
-    memcpy(playreadyHeader, mPlayreadyHeader, mPlayreadyHeaderLen);
-    *playreadyHeaderLen = mPlayreadyHeaderLen;
+    memcpy(header, mPlayreadyHeader, mPlayreadyHeaderLen);
+    *len = mPlayreadyHeaderLen;
 
     return ASF_PARSER_SUCCESS;
 }
@@ -316,8 +352,10 @@
     videoInfo->width = info->encodedImageWidth;
     videoInfo->height = info->encodedImageHeight;
 
+    // Following condition taken from Section 2.4.2.2 - Video Media Type, of Playready documentation
     if (bmp->compressionID == FOURCC('Y', 'D', 'R', 'P')) {
-        // That means PYV content
+        // That means PYV content, for which Compression Id is
+        // the last 4 bytes of the codec specific data following the Video format data
         uint32_t* ptrActCompId = (uint32_t*)((data + sizeof(AsfVideoInfoHeader) + bmp->formatDataSize - sizeof(uint32_t)));
         videoInfo->fourCC = (*ptrActCompId);
     } else {
@@ -376,7 +414,11 @@
     audioInfo->encryptedContentFlag = obj->flags.bits.encryptedContentFlag;
     audioInfo->timeOffset = obj->timeOffset;
 
-    if (format->codecIDFormatTag == 0x5052) {
+    // Codec Id is 0x5052 i.e. ASCII value of 'P', 'R' for Playready -
+    // [Refer Section 2.4.2.1 - Audio Media Type, of Playready documentation]
+    if (format->codecIDFormatTag == PRFORMATTAG) {
+    // That means protected content, for which Codec Id is
+    // the last 2 bytes of the codec specific data following the Audio format data
         uint32_t* ptrActCodecId = (uint32_t*)((data + sizeof(AsfWaveFormatEx) + format->codecSpecificDataSize - sizeof(format->codecIDFormatTag)));
         audioInfo->codecID = (*ptrActCodecId);
     } else {
@@ -426,46 +468,65 @@
         return ASF_PARSER_BAD_DATA;
     }
 
-    AsfExtendedStreamPropertiesObject *extStrObj = new AsfExtendedStreamPropertiesObject;
+    AsfExtendedStreamPropertiesObject *fixedLenExtStrPropsObj = (AsfExtendedStreamPropertiesObject *)buffer;
+    if (fixedLenExtStrPropsObj->objectSize > size) {
+        ALOGE("Invalid ASF Extended Stream Prop Object size");
+        return ASF_PARSER_BAD_VALUE;
+    }
+
+    AsfExtendedStreamPropertiesExObject *extStrObj = new AsfExtendedStreamPropertiesExObject;
     if (extStrObj == NULL) {
         return ASF_PARSER_NO_MEMORY;
     }
 
-    AsfExtendedStreamPropertiesObject *obj = (AsfExtendedStreamPropertiesObject *)buffer;
-    if (obj->objectSize > size) {
-        ALOGE("Invalid ASF Extended Stream Prop Object size");
-        delete extStrObj;
-        return ASF_PARSER_BAD_VALUE;
+    //copy all fixed length fields first.
+    memcpy(&(extStrObj->propObj), fixedLenExtStrPropsObj, sizeof(AsfExtendedStreamPropertiesObject));
+
+    ALOGD("Stream number = 0x%08X", fixedLenExtStrPropsObj->streamNumber);
+    ALOGD("PayloadExtensionSystemCount = 0x%08X", fixedLenExtStrPropsObj->payloadExtensionSystemCount);
+
+    // Get pointer to buffer where variable length fields might start
+    buffer += sizeof(AsfExtendedStreamPropertiesObject);
+
+    uint32_t streamNameOffset =  sizeof(uint16_t) * 2; // languageIDIndex + streamNameLength
+    //StramNames might start here. depends on streamNameCount.
+    for (int i = 0; i < fixedLenExtStrPropsObj->streamNameCount; i++) {
+         AsfStreamName *streamNameObj = new AsfStreamName;
+         AsfStreamName *StreamNameObjBuffer = (AsfStreamName *)buffer;
+
+         // populate the StreamName object from the buffer
+         streamNameObj->languageIDIndex = StreamNameObjBuffer->languageIDIndex;
+         streamNameObj->streamNameLength = StreamNameObjBuffer->streamNameLength;
+
+         // Allocate space to store StreamName(3rd field) for the StreamName structure
+        if (streamNameObj->streamNameLength > 0) {
+            streamNameObj->pStreamName = new uint8_t [StreamNameObjBuffer->streamNameLength];
+            if (streamNameObj->pStreamName == NULL) {
+               delete streamNameObj;
+               delete extStrObj;
+               return ASF_PARSER_NO_MEMORY;
+            }
+
+            memcpy(streamNameObj->pStreamName, buffer + streamNameOffset, StreamNameObjBuffer->streamNameLength);
+        } else {
+            // no streamName
+            streamNameObj->pStreamName = NULL;
+        }
+
+        // calculate the length of current StreamName entry.
+        // if there are multiple StreamNames  then increment
+        // buffer by  4 + streamNameLength  to point to next StreamName entry
+        buffer += streamNameOffset + StreamNameObjBuffer->streamNameLength;
+
+        extStrObj->streamNames.push_back(streamNameObj);
     }
 
-    extStrObj->objectID = obj->objectID;
-    extStrObj->objectSize = obj->objectSize;
-    extStrObj->startTime = obj->startTime;
-    extStrObj->endTime = obj->endTime;
-    extStrObj->dataBitrate = obj->dataBitrate;
-    extStrObj->bufferSize = obj->bufferSize;
-    extStrObj->initialBufferFullness = obj->initialBufferFullness;
-    extStrObj->alternateDataBitrate = obj->alternateDataBitrate;
-    extStrObj->alternateBufferSize = obj->alternateBufferSize;
-    extStrObj->alternateInitialBufferFullness = obj->alternateInitialBufferFullness;
-    extStrObj->maximumObjectSize = obj->maximumObjectSize;
-    extStrObj->flags = obj->flags;
-    extStrObj->streamNumber = obj->streamNumber;
-    extStrObj->streamLanguageIDIndex = obj->streamLanguageIDIndex;
-    extStrObj->averageTimePerFrame = obj->averageTimePerFrame;
-    extStrObj->streamNameCount = obj->streamNameCount;
-    extStrObj->payloadExtensionSystemCount = obj->payloadExtensionSystemCount;
+    uint32_t systemInfoOffset = sizeof(GUID) + sizeof(uint16_t) + sizeof(uint32_t);
+    //buffer points to extension systems here depending on payloadExtensionSystemCount in previous Fixed field.
+    for (int i = 0; i < fixedLenExtStrPropsObj->payloadExtensionSystemCount; i++) {
+        AsfPayloadExtensionSystem *extensionObj = new  AsfPayloadExtensionSystem;
+        AsfPayloadExtensionSystem *extObjData = (AsfPayloadExtensionSystem *)buffer;
 
-    ALOGD("stream number = 0x%08X", obj->streamNumber);
-    ALOGD("payloadExtensionSystemCount = 0x%08X", obj->payloadExtensionSystemCount);
-
-    // Get pointer to buffer where first extension system object starts
-    buffer = (uint8_t *)&(obj->extensionSystems);
-    int extSysSize = 0;
-    for (int i = 0; i < obj->payloadExtensionSystemCount; i++ ) {
-        extSysSize = 0;
-        PayloadExtensionSystem *extensionObj = new  PayloadExtensionSystem;
-        PayloadExtensionSystem *extObjData = (PayloadExtensionSystem *)buffer;
         // populate the extension object from the buffer
         extensionObj->extensionSystemId = extObjData->extensionSystemId;
         extensionObj->extensionDataSize = extObjData->extensionDataSize;
@@ -473,24 +534,23 @@
 
         // Allocate space to store extensionSystemInfo
         if (extensionObj->extensionSystemInfoLength > 0) {
-            // TODO: make sure this memory is freed when not reuired.
             extensionObj->extensionSystemInfo = new uint8_t [extObjData->extensionSystemInfoLength];
             if (extensionObj->extensionSystemInfo == NULL) {
                delete extensionObj;
                delete extStrObj;
                return ASF_PARSER_NO_MEMORY;
             }
-            memcpy(extensionObj->extensionSystemInfo, extObjData->extensionSystemInfo, extObjData->extensionSystemInfoLength);
+            memcpy(extensionObj->extensionSystemInfo, buffer + systemInfoOffset, extObjData->extensionSystemInfoLength);
         } else {
             // no extension system info
             extensionObj->extensionSystemInfo = NULL;
         }
 
         // calculate the length of current extension system.
-        // if there are multiple extension systems then increment buffer by  extSysSize
-        // to point to next extension object
-        extSysSize += sizeof(GUID) + sizeof(uint16_t) + sizeof(uint32_t) + extensionObj->extensionSystemInfoLength;
-        buffer += extSysSize;
+        // if there are multiple extension systems then increment
+        // buffer by  22 + extensionSystemInfoLength  to point to
+        // next extension object
+        buffer += systemInfoOffset + extensionObj->extensionSystemInfoLength;
 
         // add the extension object to the extended stream object
         extStrObj->extensionSystems.push_back(extensionObj);
@@ -547,14 +607,47 @@
     return status;
 }
 
-int AsfHeaderParser::getPayloadExtensionSystems(uint8_t streamNumber, vector<PayloadExtensionSystem *> **extSystems ) {
+
+int AsfHeaderParser::parseSampleIDFromReplicatedData(AsfPayloadDataInfo *obj, uint8_t streamNumber) {
+
+    vector<AsfPayloadExtensionSystem *> *extSystems = NULL;
+
+    // Get handle to extension systems in that stream's Extension Stream Properties object.
     for (unsigned int i = 0; i < mExtendedStreamPropertiesObj.size(); i++) {
-        if (streamNumber == mExtendedStreamPropertiesObj[i]->streamNumber) {
-            *extSystems = &(mExtendedStreamPropertiesObj[i]->extensionSystems);
-            return ASF_PARSER_SUCCESS;
+        if (streamNumber == mExtendedStreamPropertiesObj[i]->propObj.streamNumber) {
+            extSystems = &(mExtendedStreamPropertiesObj[i]->extensionSystems);
+            break;
         }
     }
-    return ASF_PARSER_FAILED;
+
+    if (extSystems == NULL) {
+        return ASF_PARSER_FAILED;
+    }
+
+    int replicatedDataOffset = 0;
+    // Find data correspodning to ASF_Payload_Extension_System_Encryption_Sample_ID which is SampleID
+    for (int i = 0; i < extSystems->size(); i++) {
+        // Point to ext system's data in replicated data buffer.
+        if ((extSystems->at(i)->extensionSystemId) == ASF_Payload_Extension_System_Encryption_Sample_ID) {
+            if (extSystems->at(i)->extensionDataSize == 0xFFFF) {
+                uint16_t extensionDataSize = *((uint16_t*) (obj->replicatedData + 8 + replicatedDataOffset));
+                obj->sampleIDLen = extensionDataSize;
+                obj->sampleID = obj->replicatedData + 8 + replicatedDataOffset + sizeof(uint16_t);  // 2 bytes denote size of this extSystem
+            } else {
+                obj->sampleID = obj->replicatedData + 8 + replicatedDataOffset;
+                obj->sampleIDLen = extSystems->at(i)->extensionDataSize;
+            }
+            return ASF_PARSER_SUCCESS;
+        }
+        // Some other extension system. Modify the replicatedData offset accordingly to point to next extension system.
+        if (extSystems->at(i)->extensionDataSize == 0xFFFF) {
+            uint16_t nSize = *((uint16_t*) (obj->replicatedData + 8 + replicatedDataOffset));
+            replicatedDataOffset += (sizeof(uint16_t) + nSize);
+        } else {
+            replicatedDataOffset += extSystems->at(i)->extensionDataSize;
+        }
+    }
+    return ASF_PARSER_UNEXPECTED_VALUE; // Other extension systems.
 }
 
 void AsfHeaderParser::resetStreamInfo() {
diff --git a/asfparser/AsfHeaderParser.h b/asfparser/AsfHeaderParser.h
index 02b8af5..285efc4 100644
--- a/asfparser/AsfHeaderParser.h
+++ b/asfparser/AsfHeaderParser.h
@@ -59,9 +59,9 @@
     bool hasVideo();
     bool hasAudio();
     bool isSeekable();
-    int getPlayreadyUuid(uint8_t* playreadyUuid);
-    int getPlayreadyHeaderXml(uint8_t* playreadyHeader, uint32_t* playreadyHeaderLen);
-    int getPayloadExtensionSystems(uint8_t streamNumber, vector<PayloadExtensionSystem *> **extSystems );
+    int getPlayreadyUuid(uint8_t playreadyUuid[], uint16_t len);
+    int getPlayreadyHeaderXml(uint8_t* header, uint32_t* len);
+    int parseSampleIDFromReplicatedData(AsfPayloadDataInfo *obj, uint8_t streamNumber);
 private:
     int onFilePropertiesObject(uint8_t *buffer, uint32_t size);
     int onStreamPropertiesObject(uint8_t *buffer, uint32_t size);
@@ -76,13 +76,12 @@
     AsfVideoStreamInfo *mVideoInfo;
     AsfFileMediaInfo  *mFileInfo;
     uint32_t mNumObjectParsed;
-    uint32_t mNumberofHeaderObjects;
     uint8_t mPlayreadyUuid[UUIDSIZE];
     bool mIsProtected;
-
     uint8_t *mPlayreadyHeader;
-    uint32_t mPlayreadyHeaderLen;
-    vector<AsfExtendedStreamPropertiesObject *> mExtendedStreamPropertiesObj;
+    uint16_t mPlayreadyHeaderLen;
+    uint32_t mNumberofHeaderObjects;
+    vector<AsfExtendedStreamPropertiesExObject *> mExtendedStreamPropertiesObj;
 };
 
 #endif
diff --git a/asfparser/AsfObjects.h b/asfparser/AsfObjects.h
index 9d92dbb..f5e3487 100644
--- a/asfparser/AsfObjects.h
+++ b/asfparser/AsfObjects.h
@@ -48,7 +48,7 @@
     uint8_t reserved2;
 };
 
-struct PlayreadyHeaderObj : AsfObject {
+struct AsfProtectionSystemIdObj : AsfObject {
     uint8_t sysId[UUIDSIZE];
     uint32_t sysVer;
     uint32_t dataSize;
@@ -157,8 +157,16 @@
     // TODO:
 };
 
+struct AsfStreamName {
+    uint16_t  languageIDIndex;
+    uint16_t  streamNameLength;
+    uint8_t  *pStreamName;
+};
+
+
+
 // objects in the ASF Header Extension object
-struct PayloadExtensionSystem {
+struct AsfPayloadExtensionSystem {
     GUID      extensionSystemId;
     uint16_t  extensionDataSize;
     uint32_t  extensionSystemInfoLength;
@@ -166,7 +174,8 @@
 };
 
 // class AsfHeaderParser;
-struct AsfExtendedStreamPropertiesObject  : AsfObject {
+// Fixed Length fields of AsfExtendedStreamPropertiesObject
+struct AsfExtendedStreamPropertiesObject : AsfObject {
     uint64_t startTime;
     uint64_t endTime;
     uint32_t dataBitrate;
@@ -191,12 +200,20 @@
     uint64_t averageTimePerFrame;
     uint16_t streamNameCount;
     uint16_t payloadExtensionSystemCount;
-    vector<PayloadExtensionSystem *> extensionSystems;
     //Stream Names - variable length
     //Payload Extension Systems - variable length
     //Stream Properties Object - variable length
 };
 
+// AsfExtendedStreamPropertiesObjectFixed + variable length extension systems.
+struct AsfExtendedStreamPropertiesExObject {
+    struct AsfExtendedStreamPropertiesObject  propObj;
+    vector<AsfStreamName *> streamNames;
+    vector<AsfPayloadExtensionSystem *> extensionSystems;
+    //Stream Properties Object - variable length
+};
+
+
 
 struct AsfAdvancedMutualExclusionObject : AsfObject {
     // TODO:
diff --git a/asfparser/AsfStreamParser.cpp b/asfparser/AsfStreamParser.cpp
index dee3c3a..b19f080 100644
--- a/asfparser/AsfStreamParser.cpp
+++ b/asfparser/AsfStreamParser.cpp
@@ -41,7 +41,6 @@
     mHeaderParser = new AsfHeaderParser;
     mDataParser = new AsfDataParser(mHeaderParser);
     mSimpleIndexParser = NULL;
-    memset(mPlayreadyUuid, 0, UUIDSIZE);
 }
 
 AsfStreamParser::~AsfStreamParser(void) {
@@ -77,20 +76,12 @@
     return ASF_PARSER_SUCCESS;
 }
 
-int AsfStreamParser::getDrmUuid(uint8_t *playreadyUuid) {
-    int status = ASF_PARSER_SUCCESS;
-
-    status = mHeaderParser->getPlayreadyUuid(playreadyUuid);
-    LOGV("AsfStreamParser::getDrmUuid() returns %x", status);
-    return status;
+int AsfStreamParser::getDrmUuid(uint8_t playreadyUuid[], uint16_t len) {
+    return mHeaderParser->getPlayreadyUuid(playreadyUuid, len);
 }
 
 int AsfStreamParser::getDrmHeaderXml(uint8_t *playreadyHeader, uint32_t *playreadyHeaderLen) {
-    int status = ASF_PARSER_SUCCESS;
-
-    status = mHeaderParser->getPlayreadyHeaderXml(playreadyHeader, playreadyHeaderLen);
-    LOGV("AsfStreamParser::getDrmHeaderXml() returns %x", status);
-    return status;
+    return mHeaderParser->getPlayreadyHeaderXml(playreadyHeader, playreadyHeaderLen);
 }
 AsfAudioStreamInfo* AsfStreamParser::getAudioInfo() const {
     return mHeaderParser->getAudioInfo();
diff --git a/asfparser/AsfStreamParser.h b/asfparser/AsfStreamParser.h
index e5fd0c4..5fb8acf 100644
--- a/asfparser/AsfStreamParser.h
+++ b/asfparser/AsfStreamParser.h
@@ -43,7 +43,7 @@
     AsfAudioStreamInfo* getAudioInfo() const;
     AsfVideoStreamInfo* getVideoInfo() const;
     AsfFileMediaInfo* getFileInfo() const;
-    int getDrmUuid(uint8_t* playreadyUuid);
+    int getDrmUuid(uint8_t playreadyUuid[], uint16_t len);
     int getDrmHeaderXml(uint8_t* playreadyHeader, uint32_t* playreadyHeaderLen);
 
     // return duration in 100-nanosecond unit , readable when header object is parsed
@@ -81,7 +81,6 @@
     // Preroll value is used for data buffering.
     uint32_t mTimeOffsetMs;
     bool mHeaderParsed;
-    uint8_t mPlayreadyUuid[UUIDSIZE];
     class AsfHeaderParser *mHeaderParser;
     class AsfDataParser *mDataParser;
     class AsfSimpleIndexParser *mSimpleIndexParser;