bool WriteChunk ( LFA_FileRef inFileRef, long tagID, const char * data, UInt32 len ) { atag ck; ck.id = MakeUns32LE ( tagID ); ck.len = MakeUns32LE ( len ); try { LFA_Write ( inFileRef, &ck, 8 ); LFA_Write ( inFileRef, data, len ); } catch ( ... ) { return false; } return true; }
bool MarkChunkAsPadding ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, long tagID, long subtypeID ) { UInt32 len; UInt64 pos; atag tag; try { bool found = FindChunk ( inOutRiffState, tagID, riffType, subtypeID, NULL, &len, &pos ); if ( ! found ) return false; if ( subtypeID != 0 ) { pos -= 12; } else { pos -= 8; } tag.id = MakeUns32LE ( ckidPremierePadding ); LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, &tag, 4 ); pos += 8; AddTag ( inOutRiffState, ckidPremierePadding, len, pos, 0, 0, 0 ); } catch(...) { return false; // If a write fails, it throws, so we return false. } return true; }
bool WriteFileAttrFlags ( LFA_FileRef fileRef, const TagData& fileAttrTag, XMP_Uns32 flags ) { try { XMP_Uns32 bitMask = MakeUns32LE ( flags ); LFA_Seek ( fileRef, fileAttrTag.pos + fileAttrTag.offset, SEEK_SET ); LFA_Write ( fileRef, &bitMask, 4 ); return true; } catch ( ... ) {} return false; } // WriteFileAttrFlags
bool ASF_Support::WriteHeaderExtensionObject ( const std::string& buffer, std::string* header, const ASF_ObjectBase& _objectBase, const int /*reservePadding*/ ) { if ( ! IsEqualGUID ( ASF_Header_Extension_Object, _objectBase.guid ) || (! header) || (buffer.size() < 46) ) return false; const XMP_Uns64 offset = 46; int startPos = header->size(); // copy header base header->append ( buffer, 0, offset ); // read extended header-object structure beginning at the data part (offset = 46) XMP_Uns64 read = 0; XMP_Uns64 data = (_objectBase.size - offset); XMP_Uns64 pos = offset; ASF_ObjectBase objectBase; while ( read < data ) { memcpy ( &objectBase, &buffer[int(pos)], kASF_ObjectBaseLen ); objectBase.size = GetUns64LE ( &objectBase.size ); if ( IsEqualGUID ( ASF_Padding_Object, objectBase.guid ) ) { // eliminate } else { // copy other objects header->append ( buffer, XMP_Uns32(pos), XMP_Uns32(objectBase.size) ); } pos += objectBase.size; read += objectBase.size; } // update header extension data size XMP_Uns32 valueUns32LE = MakeUns32LE ( header->size() - startPos - offset ); std::string newDataSize ( (const char*)&valueUns32LE, 4 ); ReplaceString ( *header, newDataSize, (startPos + 42), 4 ); // update new object size XMP_Uns64 valueUns64LE = MakeUns64LE ( header->size() - startPos ); std::string newObjectSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( *header, newObjectSize, (startPos + 16), 8 ); return true; }
bool WriteXMPTag ( LFA_FileRef fileRef, XMP_Uns32 len, const char* inBuffer ) { bool ret = false; XMP_Uns16 code = MakeUns16LE ( (SWF_TAG_ID_METADATA << 6) | 0x3F ); XMP_Uns32 length = MakeUns32LE ( len ); try { LFA_Write (fileRef, &code, 2 ); LFA_Write (fileRef, &length, 4 ); LFA_Write (fileRef, inBuffer, len ); ret = true; } catch ( ... ) {} return ret; } // WriteXMPTag
bool PutChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, long tagID, const char * inBuffer, UInt32 inBufferSize ) { UInt32 len; UInt64 pos; atag tag; // Make sure we're writting an even number of bytes. Required by the RIFF specification. XMP_Assert ( (inBufferSize & 1) == 0 ); try { bool found = FindChunk ( inOutRiffState, tagID, 0, 0, NULL, &len, &pos ); if ( found ) { if ( len == inBufferSize ) { LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, inBuffer, inBufferSize ); return true; } pos -= 8; tag.id = MakeUns32LE ( ckidPremierePadding ); LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, &tag, 4 ); if ( len > inBufferSize ) { pos += 8; AddTag ( inOutRiffState, ckidPremierePadding, len, pos, 0, 0, 0 ); } } } catch ( ... ) { // If a write fails, it throws, so we return false return false; } bool ok = MakeChunk ( inFileRef, inOutRiffState, riffType, (inBufferSize + 8) ); if ( ! ok ) return false; return WriteChunk ( inFileRef, tagID, inBuffer, inBufferSize ); }
bool UpdateHeader ( LFA_FileRef fileRef ) { try { XMP_Int64 length64 = LFA_Measure ( fileRef ); if ( (length64 < 8) || (length64 > (XMP_Int64)0xFFFFFFFFULL) ) return false; XMP_Uns32 length32 = MakeUns32LE ( (XMP_Uns32)length64 ); LFA_Seek ( fileRef, 4, SEEK_SET ); LFA_Write ( fileRef, &length32, 4 ); return true; } catch ( ... ) {} return false; } // UpdateHeader
typedef struct _GUID { XMP_Uns32 Data1; XMP_Uns16 Data2; XMP_Uns16 Data3; XMP_Uns8 Data4[8]; } GUID; int IsEqualGUID ( const GUID& guid1, const GUID& guid2 ); static const GUID GUID_NULL = { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }; #endif // header object static const GUID ASF_Header_Object = { MakeUns32LE(0x75b22630), MakeUns16LE(0x668e), MakeUns16LE(0x11cf), { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c } }; // contains ... static const GUID ASF_File_Properties_Object = { MakeUns32LE(0x8cabdca1), MakeUns16LE(0xa947), MakeUns16LE(0x11cf), { 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 } }; static const GUID ASF_Content_Description_Object = { MakeUns32LE(0x75b22633), MakeUns16LE(0x668e), MakeUns16LE(0x11cf), { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c } }; static const GUID ASF_Content_Branding_Object = { MakeUns32LE(0x2211b3fa), MakeUns16LE(0xbd23), MakeUns16LE(0x11d2), { 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e } }; static const GUID ASF_Content_Encryption_Object = { MakeUns32LE(0x2211b3fb), MakeUns16LE(0xbd23), MakeUns16LE(0x11d2), { 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e } }; // padding // Remark: regarding to Microsofts spec only the ASF_Header_Object contains a ASF_Padding_Object // Real world files show, that the ASF_Header_Extension_Object contains a ASF_Padding_Object static const GUID ASF_Header_Extension_Object = { MakeUns32LE(0x5fbf03b5), MakeUns16LE(0xa92e), MakeUns16LE(0x11cf), { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 } }; static const GUID ASF_Padding_Object = { MakeUns32LE(0x1806d474), MakeUns16LE(0xcadf), MakeUns16LE(0x4509), { 0xa4, 0xba, 0x9a, 0xab, 0xcb, 0x96, 0xaa, 0xe8 } }; // data object static const GUID ASF_Data_Object = { MakeUns32LE(0x75b22636), MakeUns16LE(0x668e), MakeUns16LE(0x11cf), { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c } }; // XMP object
bool ASF_Support::WriteHeaderObject ( XMP_IO* sourceRef, XMP_IO* destRef, const ObjectData& object, ASF_LegacyManager& _legacyManager, bool usePadding ) { if ( ! IsEqualGUID ( ASF_Header_Object, object.guid ) ) return false; std::string buffer; XMP_Uns16 valueUns16LE; XMP_Uns32 valueUns32LE; XMP_Uns64 valueUns64LE; try { // read header-object structure XMP_Uns64 pos = object.pos; XMP_Uns32 bufferSize = kASF_ObjectBaseLen + 6; buffer.clear(); buffer.reserve ( bufferSize ); buffer.assign ( bufferSize, ' ' ); sourceRef->Seek ( pos, kXMP_SeekFromStart ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), bufferSize ); XMP_Uns64 read = bufferSize; pos += bufferSize; // read contained header objects /*XMP_Uns32 numberOfHeaders = GetUns32LE ( &buffer[24] );*/ ASF_ObjectBase objectBase; // prepare new header in memory std::string header; int changedObjects = _legacyManager.changedObjects(); int exportedObjects = 0; int writtenObjects = 0; header.append ( buffer.c_str(), bufferSize ); while ( read < object.len ) { sourceRef->Seek ( pos, kXMP_SeekFromStart ); if ( kASF_ObjectBaseLen != sourceRef->Read ( &objectBase, kASF_ObjectBaseLen, true ) ) break; sourceRef->Seek ( pos, kXMP_SeekFromStart ); objectBase.size = GetUns64LE ( &objectBase.size ); int headerStartPos = header.size(); // save position of filesize-information if ( IsEqualGUID ( ASF_File_Properties_Object, objectBase.guid ) ) { posFileSizeInfo = (headerStartPos + 40); } // write objects if ( IsEqualGUID ( ASF_File_Properties_Object, objectBase.guid ) && (objectBase.size >= 104) && (changedObjects & ASF_LegacyManager::objectFileProperties) ) { // copy object and replace creation-date buffer.reserve ( XMP_Uns32 ( objectBase.size ) ); buffer.assign ( XMP_Uns32 ( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); header.append ( buffer, 0, XMP_Uns32( objectBase.size ) ); if ( ! _legacyManager.GetBroadcast() ) { buffer = _legacyManager.GetField ( ASF_LegacyManager::fieldCreationDate ); ReplaceString ( header, buffer, (headerStartPos + 48), 8 ); } exportedObjects |= ASF_LegacyManager::objectFileProperties; } else if ( IsEqualGUID ( ASF_Content_Description_Object, objectBase.guid ) && (objectBase.size >= 34) && (changedObjects & ASF_LegacyManager::objectContentDescription) ) { // re-create object with xmp-data buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // write header only header.append ( buffer, 0, XMP_Uns32( kASF_ObjectBaseLen ) ); // write length fields XMP_Uns16 titleLen = _legacyManager.GetField ( ASF_LegacyManager::fieldTitle).size( ); valueUns16LE = MakeUns16LE ( titleLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 authorLen = _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor).size( ); valueUns16LE = MakeUns16LE ( authorLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 copyrightLen = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright).size( ); valueUns16LE = MakeUns16LE ( copyrightLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 descriptionLen = _legacyManager.GetField ( ASF_LegacyManager::fieldDescription).size( ); valueUns16LE = MakeUns16LE ( descriptionLen ); header.append ( (const char*)&valueUns16LE, 2 ); // retrieve existing overall length of preceding fields XMP_Uns16 precedingLen = 0; precedingLen += GetUns16LE ( &buffer[24] ); // Title precedingLen += GetUns16LE ( &buffer[26] ); // Author precedingLen += GetUns16LE ( &buffer[28] ); // Copyright precedingLen += GetUns16LE ( &buffer[30] ); // Description // retrieve existing 'Rating' length XMP_Uns16 ratingLen = GetUns16LE ( &buffer[32] ); // Rating valueUns16LE = MakeUns16LE ( ratingLen ); header.append ( (const char*)&valueUns16LE, 2 ); // write field contents header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldTitle ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldDescription ) ); header.append ( buffer, (34 + precedingLen), ratingLen ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); exportedObjects |= ASF_LegacyManager::objectContentDescription; } else if ( IsEqualGUID ( ASF_Content_Branding_Object, objectBase.guid ) && (changedObjects & ASF_LegacyManager::objectContentBranding) ) { // re-create object with xmp-data buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // calculate size of fields coming before 'Copyright URL' XMP_Uns32 length = 28; length += (GetUns32LE ( &buffer[length] ) + 4); // Banner Image Data length += (GetUns32LE ( &buffer[length] ) + 4); // Banner Image URL // write first part of header header.append ( buffer, 0, length ); // copyright URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); exportedObjects |= ASF_LegacyManager::objectContentBranding; #if ! Exclude_LicenseURL_Recon } else if ( IsEqualGUID ( ASF_Content_Encryption_Object, objectBase.guid ) && (changedObjects & ASF_LegacyManager::objectContentEncryption) ) { // re-create object with xmp-data buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // calculate size of fields coming before 'License URL' XMP_Uns32 length = 24; length += (GetUns32LE ( &buffer[length] ) + 4); // Secret Data length += (GetUns32LE ( &buffer[length] ) + 4); // Protection Type length += (GetUns32LE ( &buffer[length] ) + 4); // Key ID // write first part of header header.append ( buffer, 0, length ); // License URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); exportedObjects |= ASF_LegacyManager::objectContentEncryption; #endif } else if ( IsEqualGUID ( ASF_Header_Extension_Object, objectBase.guid ) && usePadding ) { // re-create object if padding needs to be used buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); ASF_Support::WriteHeaderExtensionObject ( buffer, &header, objectBase, 0 ); } else if ( IsEqualGUID ( ASF_Padding_Object, objectBase.guid ) && usePadding ) { // eliminate padding (will be created as last object) } else { // simply copy all other objects buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); header.append ( buffer, 0, XMP_Uns32( objectBase.size ) ); } pos += objectBase.size; read += objectBase.size; writtenObjects ++; } // any objects to create ? int newObjects = (changedObjects ^ exportedObjects); if ( newObjects ) { // create new objects with xmp-data int headerStartPos; ASF_ObjectBase newObjectBase; XMP_Uns32 length; if ( newObjects & ASF_LegacyManager::objectContentDescription ) { headerStartPos = header.size(); newObjectBase.guid = ASF_Content_Description_Object; newObjectBase.size = 0; // write object header header.append ( (const char*)&newObjectBase, kASF_ObjectBaseLen ); XMP_Uns16 titleLen = _legacyManager.GetField ( ASF_LegacyManager::fieldTitle).size( ); valueUns16LE = MakeUns16LE ( titleLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 authorLen = _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor).size( ); valueUns16LE = MakeUns16LE ( authorLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 copyrightLen = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright).size( ); valueUns16LE = MakeUns16LE ( copyrightLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 descriptionLen = _legacyManager.GetField ( ASF_LegacyManager::fieldDescription).size( ); valueUns16LE = MakeUns16LE ( descriptionLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 ratingLen = 0; valueUns16LE = MakeUns16LE ( ratingLen ); header.append ( (const char*)&valueUns16LE, 2 ); // write field contents header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldTitle ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldDescription ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); newObjects &= ~ASF_LegacyManager::objectContentDescription; writtenObjects ++; } if ( newObjects & ASF_LegacyManager::objectContentBranding ) { headerStartPos = header.size(); newObjectBase.guid = ASF_Content_Branding_Object; newObjectBase.size = 0; // write object header header.append ( (const char*)&newObjectBase, kASF_ObjectBaseLen ); // write 'empty' fields header.append ( 12, '\0' ); // copyright URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); newObjects &= ~ASF_LegacyManager::objectContentBranding; writtenObjects ++; } #if ! Exclude_LicenseURL_Recon if ( newObjects & ASF_LegacyManager::objectContentEncryption ) { headerStartPos = header.size(); newObjectBase.guid = ASF_Content_Encryption_Object; newObjectBase.size = 0; // write object header header.append ( (const char*)&newObjectBase, kASF_ObjectBaseLen ); // write 'empty' fields header.append ( 12, '\0' ); // License URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); newObjects &= ~ASF_LegacyManager::objectContentEncryption; writtenObjects ++; } #endif } // create padding object ? if ( usePadding && (header.size ( ) < object.len ) ) { ASF_Support::CreatePaddingObject ( &header, (object.len - header.size()) ); writtenObjects ++; } // update new header-object size valueUns64LE = MakeUns64LE ( header.size() ); std::string newValue ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newValue, 16, 8 ); // update new number of Header objects valueUns32LE = MakeUns32LE ( writtenObjects ); newValue = std::string ( (const char*)&valueUns32LE, 4 ); ReplaceString ( header, newValue, 24, 4 ); // if we are operating on the same file (in-place update), place pointer before writing if ( sourceRef == destRef ) destRef->Seek ( object.pos, kXMP_SeekFromStart ); if ( this->progressTracker != 0 ) { XMP_Assert ( this->progressTracker->WorkInProgress() ); this->progressTracker->AddTotalWork ( (float)header.size() ); } // write header destRef->Write ( header.c_str(), header.size() ); } catch ( ... ) { return false; } return true; }
bool MakeChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, UInt32 len ) { long starttag; UInt32 taglen; UInt32 rifflen, avail; UInt64 pos; /* look for top level Premiere padding chunk */ starttag = 0; while ( FindChunk ( inOutRiffState, ckidPremierePadding, riffType, 0, &starttag, &taglen, &pos ) ) { pos -= 8; taglen += 8; long extra = taglen - len; if ( extra < 0 ) continue; RiffIterator iter = inOutRiffState.tags.begin(); iter += (starttag - 1); if ( extra == 0 ) { iter->len = 0; } else { atag pad; UInt64 padpos; /* need 8 bytes extra to be able to split it */ extra -= 8; if ( extra < 0 ) continue; try{ padpos = pos + len; LFA_Seek ( inFileRef, padpos, SEEK_SET ); pad.id = MakeUns32LE ( ckidPremierePadding ); pad.len = MakeUns32LE ( extra ); LFA_Write ( inFileRef, &pad, sizeof(pad) ); } catch ( ... ) { return false; } iter->pos = padpos + 8; iter->len = extra; } /* seek back to start of original padding chunk */ LFA_Seek ( inFileRef, pos, SEEK_SET ); return true; } /* can't take padding chunk, so append new chunk to end of file */ rifflen = inOutRiffState.rifflen + 8; avail = AVIMAXCHUNKSIZE - rifflen; LFA_Seek ( inFileRef, 0, SEEK_END ); pos = GetFilePosition ( inFileRef ); if ( (pos & 1) == 1 ) { // The file length is odd, need a pad byte. XMP_Uns8 pad = 0; LFA_Write ( inFileRef, &pad, 1 ); ++pos; } if ( avail < len ) { /* if needed, create new AVIX chunk */ ltag avix; avix.id = MakeUns32LE ( FOURCC_RIFF ); avix.len = MakeUns32LE ( 4 + len ); avix.subid = MakeUns32LE ( formtypeAVIX ); LFA_Write(inFileRef, &avix, sizeof(avix)); pos += 12; AddTag ( inOutRiffState, avix.id, len, pos, 0, 0, 0 ); } else { /* otherwise, rewrite length of last RIFF chunk in file */ pos = inOutRiffState.riffpos + 4; rifflen = inOutRiffState.rifflen + len; XMP_Uns32 fileLen = MakeUns32LE ( rifflen ); LFA_Seek ( inFileRef, pos, SEEK_SET ); LFA_Write ( inFileRef, &fileLen, 4 ); inOutRiffState.rifflen = rifflen; /* prepare to write data */ LFA_Seek ( inFileRef, 0, SEEK_END ); } return true; }
static inline XMP_Uns32 ReadUns32_LE ( XMP_IO* file ) { XMP_Uns32 value; file->ReadAll ( &value, 4 ); return MakeUns32LE ( value ); }
static inline void WriteUns32_LE ( XMP_IO* file, XMP_Uns32 value ) { XMP_Uns32 v = MakeUns32LE ( value ); file->Write ( &v, 4 ); }