diff options
Diffstat (limited to 'source/XMPFiles/FileHandlers/AVI_Handler.cpp')
-rw-r--r-- | source/XMPFiles/FileHandlers/AVI_Handler.cpp | 498 |
1 files changed, 0 insertions, 498 deletions
diff --git a/source/XMPFiles/FileHandlers/AVI_Handler.cpp b/source/XMPFiles/FileHandlers/AVI_Handler.cpp deleted file mode 100644 index 96a11ec..0000000 --- a/source/XMPFiles/FileHandlers/AVI_Handler.cpp +++ /dev/null @@ -1,498 +0,0 @@ -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2008 Adobe Systems Incorporated -// All Rights Reserved -// -// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms -// of the Adobe license agreement accompanying it. -// ================================================================================================= - -#include "AVI_Handler.hpp" -#include "RIFF_Support.hpp" - -#if XMP_WinBuild - #include <vfw.h> -#else - #ifndef formtypeAVI - #define formtypeAVI MakeFourCC('A', 'V', 'I', ' ') - #else - #error "formtypeAVI already defined" - #endif -#endif - -using namespace std; - -#define kXMPUserDataType MakeFourCC ( '_', 'P', 'M', 'X' ) /* Yes, backwards! */ - -// FourCC codes for the RIFF chunks -#define aviTimeChunk MakeFourCC('I','S','M','T') -#define avihdrlChunk MakeFourCC('h','d','r','l') -#define myOrgTimeChunk MakeFourCC('t','c','_','O') /* 0x4f5f6374 */ -#define myAltTimeChunk MakeFourCC('t','c','_','A') -#define myOrgReelChunk MakeFourCC('r','n','_','O') /* 0x4f5f6e72 */ -#define myAltReelChunk MakeFourCC('r','n','_','A') -#define myCommentChunk MakeFourCC('c','m','n','t') -#define myTimeList MakeFourCC('T','d','a','t') /* 0x74616454 */ -#define myCommentList MakeFourCC('C','d','a','t') - -#define TIMELEN 18 -#define REELLEN 40 -#define REALTIMELEN 11 -#define COMMENTLEN 256 - -/* list id (4 bytes) + four tags hdrs (8 each) + 2 TIMEs + 2 REELs */ -#define PR_AVI_TIMELEN (12 + 2 * (8 + TIMELEN) + 2 * (8 + REELLEN)) - -#define PR_AVI_COMMENTLEN (12 + 8 + COMMENTLEN) - -#define kStartTimecode "startTimecode" -#define kTimeValue "timeValue" -#define kAltTimecode "altTimecode" -#define kTapeName "tapeName" -#define kAltTapeName "altTapeName" -#define kLogComment "logComment" - -// ================================================================================================= -/// \file AVI_Handler.cpp -/// \brief File format handler for AVI. -/// -/// This header ... -/// -// ================================================================================================= - -// ================================================================================================= -// AVI_MetaHandlerCTor -// ==================== - -XMPFileHandler * AVI_MetaHandlerCTor ( XMPFiles * parent ) -{ - return new AVI_MetaHandler ( parent ); - -} // AVI_MetaHandlerCTor - -// ================================================================================================= -// AVI_CheckFormat -// =============== -// -// An AVI file must begin with "RIFF", a 4 byte little endian length, then "AVI ". The length should -// be fileSize-8, but we don't bother checking this here. - -bool AVI_CheckFormat ( XMP_FileFormat format, - XMP_StringPtr filePath, - LFA_FileRef fileRef, - XMPFiles * parent ) -{ - IgnoreParam(format); IgnoreParam(parent); - XMP_Assert ( format == kXMP_AVIFile ); - - if ( fileRef == 0 ) return false; - - enum { kBufferSize = 12 }; - XMP_Uns8 buffer [kBufferSize]; - - LFA_Seek ( fileRef, 0, SEEK_SET ); - LFA_Read ( fileRef, buffer, kBufferSize ); - - // "RIFF" is 52 49 46 46, "AVI " is 41 56 49 20 - if ( (! CheckBytes ( &buffer[0], "\x52\x49\x46\x46", 4 )) || - (! CheckBytes ( &buffer[8], "\x41\x56\x49\x20", 4 )) ) return false; - - return true; - -} // AVI_CheckFormat - -// ================================================================================================= -// AVI_MetaHandler::AVI_MetaHandler -// ================================ - -AVI_MetaHandler::AVI_MetaHandler ( XMPFiles * _parent ) -{ - this->parent = _parent; - this->handlerFlags = kAVI_HandlerFlags; - this->stdCharForm = kXMP_Char8Bit; - -} // AVI_MetaHandler::AVI_MetaHandler - -// ================================================================================================= -// AVI_MetaHandler::~AVI_MetaHandler -// ================================= - -AVI_MetaHandler::~AVI_MetaHandler() -{ - // Nothing to do. - -} // AVI_MetaHandler::~AVI_MetaHandler - -// ================================================================================================= -// AVI_MetaHandler::UpdateFile -// =========================== - -void AVI_MetaHandler::UpdateFile ( bool doSafeUpdate ) -{ - bool ok; - - if ( ! this->needsUpdate ) return; - if ( doSafeUpdate ) XMP_Throw ( "AVI_MetaHandler::UpdateFile: Safe update not supported", kXMPErr_Unavailable ); - - XMP_StringPtr packetStr = xmpPacket.c_str(); - XMP_StringLen packetLen = (XMP_StringLen)xmpPacket.size(); - if ( packetLen == 0 ) return; - - // Make sure we're writing an even number of bytes as required by the RIFF specification. - if ( (xmpPacket.size() & 1) == 1 ) xmpPacket.push_back ( ' ' ); - XMP_Assert ( (xmpPacket.size() & 1) == 0 ); - packetStr = xmpPacket.c_str(); // ! Make sure they are current. - packetLen = (XMP_StringLen)xmpPacket.size(); - - LFA_FileRef fileRef(this->parent->fileRef); - if ( fileRef == 0 ) return; - - RIFF_Support::RiffState riffState; - long numTags = RIFF_Support::OpenRIFF ( fileRef, riffState ); - if ( numTags == 0 ) return; - - ok = RIFF_Support::PutChunk ( fileRef, riffState, formtypeAVI, kXMPUserDataType, (char*)packetStr, packetLen ); - if ( ! ok ) return; // If there's an error writing the chunk, bail. - - ok = CreatorAtom::Update ( this->xmpObj, fileRef, formtypeAVI, riffState ); - if ( ! ok ) return; - - // Update legacy metadata - - std::string startTimecodeString, altTimecodeString, orgReelString, altReelString, logCommentString; - - this->xmpObj.GetStructField ( kXMP_NS_DM, kStartTimecode, kXMP_NS_DM, kTimeValue, &startTimecodeString, 0 ); - this->xmpObj.GetStructField ( kXMP_NS_DM, kAltTimecode, kXMP_NS_DM, kTimeValue, &altTimecodeString, 0 ); - this->xmpObj.GetProperty ( kXMP_NS_DM, kTapeName, &orgReelString, 0 ); - this->xmpObj.GetProperty ( kXMP_NS_DM, kAltTapeName, &altReelString, 0 ); - this->xmpObj.GetProperty ( kXMP_NS_DM, kLogComment, &logCommentString, 0 ); - - if ( startTimecodeString.size() != 0 ) { - // I'm not sure why we copy into this 12 char buffer, but this is what Premiere code does. - char aviTime [12]; - memset ( aviTime, 0, 12 ); - memcpy ( aviTime, startTimecodeString.data(), 11 ); // AUDIT: 11 is less than 12 - RewriteChunk ( fileRef, riffState, aviTimeChunk, avihdrlChunk, aviTime ); - } - - if ( logCommentString.size() != 0 ) { - - ok = FindChunk ( riffState, myCommentChunk, myCommentList, 0, 0, 0, 0 ); - - if ( ok ) { - - // Always rewrite the comment string, even if empty, so the user can erase it. - RIFF_Support::RewriteChunk ( fileRef, riffState, myCommentChunk, myCommentList, logCommentString.c_str() ); - - } else { - - ok = MakeChunk ( fileRef, riffState, formtypeAVI, PR_AVI_COMMENTLEN ); - if ( ! ok ) return; // If there's an error making a chunk, bail - - RIFF_Support::ltag listtag; - listtag.id = MakeUns32LE ( FOURCC_LIST ); - listtag.len = MakeUns32LE ( PR_AVI_COMMENTLEN - 8 ); - listtag.subid = MakeUns32LE ( myCommentList ); - LFA_Write ( fileRef, &listtag, 12 ); - - RIFF_Support::WriteChunk ( fileRef, myCommentChunk, logCommentString.c_str(), COMMENTLEN ); - - } - - } - - ok = RIFF_Support::FindChunk ( riffState, myOrgTimeChunk, myTimeList, 0, 0, 0, 0 ); - - if ( ok ) { - - if ( startTimecodeString.size() != 0 ) { - RewriteChunk ( fileRef, riffState, myOrgTimeChunk, myTimeList, startTimecodeString.c_str() ); - } - - if ( altTimecodeString.size() != 0 ) { - RewriteChunk ( fileRef, riffState, myAltTimeChunk, myTimeList, altTimecodeString.c_str() ); - } - - // Always rewrite the reel strings, even if empty, so the user can erase them. - RewriteChunk ( fileRef, riffState, myOrgReelChunk, myTimeList, orgReelString.c_str() ); - RewriteChunk ( fileRef, riffState, myAltReelChunk, myTimeList, altReelString.c_str() ); - - } else { - - // We don't have the legacy part yet. If none of the XMP items exist then don't do anything. - // Otherwise, add all 4 even if empty. This is the original logic from way back. - - bool haveAnyXMP = ( (! startTimecodeString.empty()) || (! altTimecodeString.empty()) || - (! orgReelString.empty()) || (! altReelString.empty()) ); - - if ( haveAnyXMP ) { - - ok = MakeChunk ( fileRef, riffState, formtypeAVI, PR_AVI_TIMELEN ); - if ( ! ok ) return; // If there's an error making a chunk, bail - - RIFF_Support::ltag listtag; - listtag.id = MakeUns32LE ( FOURCC_LIST ); - listtag.len = MakeUns32LE ( PR_AVI_TIMELEN - 8 ); - listtag.subid = MakeUns32LE ( myTimeList ); - LFA_Write(fileRef, &listtag, 12); - - RIFF_Support::WriteChunk ( fileRef, myOrgTimeChunk, startTimecodeString.c_str(), TIMELEN ); - RIFF_Support::WriteChunk ( fileRef, myAltTimeChunk, altTimecodeString.c_str(), TIMELEN ); - RIFF_Support::WriteChunk ( fileRef, myOrgReelChunk, orgReelString.c_str(), REELLEN ); - RIFF_Support::WriteChunk ( fileRef, myAltReelChunk, altReelString.c_str(), REELLEN ); - - } - - } - - this->needsUpdate = false; - -} // AVI_MetaHandler::UpdateFile - -// ================================================================================================= -// AVI_MetaHandler::WriteFile -// ========================== - -void AVI_MetaHandler::WriteFile ( LFA_FileRef sourceRef, - const std::string & sourcePath ) -{ - IgnoreParam(sourceRef); IgnoreParam(sourcePath); - - XMP_Throw ( "AVI_MetaHandler::WriteFile: Not supported", kXMPErr_Unavailable ); - -} // AVI_MetaHandler::WriteFile - -// ================================================================================================= - -static void StripSimpleEmpty ( SXMPMeta * xmp, XMP_StringPtr ns, XMP_StringPtr prop ) -{ - // Small hack to clean up bad data. There are cases of code writing xmpDM:startTimecode and - // xmpDM:altTimecode as simple properties with empty values. They are supposed to be structs. - - std::string value; - XMP_OptionBits flags; - - bool found = xmp->GetProperty ( ns, prop, &value, &flags ); - - if ( found && XMP_PropIsSimple(flags) && value.empty() ) { - xmp->DeleteProperty ( ns, prop ); - } - -} - -// ================================================================================================= -// AVI_MetaHandler::CacheFileData -// ============================== - -void AVI_MetaHandler::CacheFileData() -{ - bool ok; - - this->containsXMP = false; - - LFA_FileRef fileRef ( this->parent->fileRef ); //*** simplify to assignment - if ( fileRef == 0 ) return; - - bool updateFile = XMP_OptionIsSet ( this->parent->openFlags, kXMPFiles_OpenForUpdate ); - if ( updateFile ) { - - // Workaround for bad files in the field that have a bad size in the outermost RIFF chunk. - // Repair the cases where the length is too long (beyond EOF). Don't repair a length that is - // less than EOF, we don't know if there actually are multiple top level chunks. There is - // also a check and "runtime repair" inside ReadTag, needed for read-only file access. - - XMP_Int64 fileLen = LFA_Measure ( fileRef ); - XMP_Uns32 riffLen; - - LFA_Seek ( fileRef, 4, SEEK_SET ); - LFA_Read ( fileRef, &riffLen, 4 ); - riffLen = GetUns32LE ( &riffLen ); - - if ( (fileLen >= 8) && ((XMP_Int64)riffLen > (fileLen - 8)) ) { // Is the initial chunk too long? - - bool repairFile = XMP_OptionIsSet ( this->parent->openFlags, kXMPFiles_OpenRepairFile ); - if ( ! repairFile ) { - XMP_Throw ( "Initial RIFF tag exceeds file length", kXMPErr_BadValue ); - } else { - riffLen = MakeUns32LE ( (XMP_Uns32)fileLen - 8 ); - LFA_Seek ( fileRef, 4, SEEK_SET ); - LFA_Write ( fileRef, &riffLen, 4 ); - } - - } - - } - - // Contnue with normal processing. - - RIFF_Support::RiffState riffState; - long numTags = RIFF_Support::OpenRIFF ( fileRef, riffState ); - if ( numTags == 0 ) return; //*** shouldn't we throw ? XMP_Throw("invalid file format") or such? - - // Determine the size of the metadata - unsigned long bufferSize(0); - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, kXMPUserDataType /* _PMX, the xmp packet */, 0, 0, 0, &bufferSize); - - if ( ! ok ) { - - packetInfo.writeable = true; // If no packet found, created packets will be writeable. - - } else if ( bufferSize > 0 ) { - - // Size and clear the buffer - this->xmpPacket.reserve ( bufferSize ); - this->xmpPacket.assign ( bufferSize, ' ' ); - - // Get the metadata - XMP_Uns64 xmpPacketPosition; - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, kXMPUserDataType /* _PMX, the xmp packet */, 0, 0, - (char*)this->xmpPacket.c_str(), &bufferSize, &xmpPacketPosition ); - if ( ok ) { - this->packetInfo.offset = xmpPacketPosition; - this->packetInfo.length = bufferSize; - this->xmpObj.ParseFromBuffer ( this->xmpPacket.c_str(), (XMP_StringLen)this->xmpPacket.size() ); - this->containsXMP = true; - } - - } - - // Reconcile legacy metadata. - - std::string aviTimeString, orgTimeString, altTimeString, projectPathString; - unsigned long aviTimeSize, orgTimeSize, altTimeSize; - - StripSimpleEmpty ( &this->xmpObj, kXMP_NS_DM, kStartTimecode ); - StripSimpleEmpty ( &this->xmpObj, kXMP_NS_DM, kAltTimecode ); - - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, aviTimeChunk, avihdrlChunk, 0, 0, &aviTimeSize ); - if ( ok ) { - aviTimeString.reserve ( aviTimeSize ); - aviTimeString.assign ( aviTimeSize, ' ' ); - RIFF_Support::GetRIFFChunk ( fileRef, riffState, aviTimeChunk, avihdrlChunk, 0, (char*)aviTimeString.c_str(), &aviTimeSize ); - } - - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, myOrgTimeChunk, myTimeList, 0, 0, &orgTimeSize ); - if ( ok ) { - orgTimeString.reserve ( orgTimeSize ); - orgTimeString.assign ( orgTimeSize, ' ' ); - RIFF_Support::GetRIFFChunk ( fileRef, riffState, myOrgTimeChunk, myTimeList, 0, (char*)orgTimeString.c_str(), &orgTimeSize ); - } - - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, myAltTimeChunk, myTimeList, 0, 0, &altTimeSize ); - if ( ok ) { - altTimeString.reserve ( altTimeSize ); - altTimeString.assign ( altTimeSize, ' ' ); - RIFF_Support::GetRIFFChunk ( fileRef, riffState, myAltTimeChunk, myTimeList, 0, (char*)altTimeString.c_str(), &altTimeSize ); - } - - if ( (! aviTimeString.empty()) && orgTimeString.empty() && (altTimeString.empty()) ) { - - // If we have an avi time, and not the org or alt, use the avi. I suspect this is for some earlier backwards compatibility. - - std::string xmpString; - this->xmpObj.GetStructField ( kXMP_NS_DM, kStartTimecode, kXMP_NS_DM, kTimeValue, &xmpString, 0 ); - if ( xmpString.compare ( 0, REALTIMELEN, aviTimeString, 0, REALTIMELEN ) ) { - this->xmpObj.SetStructField ( kXMP_NS_DM, kStartTimecode, kXMP_NS_DM, kTimeValue, aviTimeString, 0 ); - this->containsXMP = true; - } - - } else { - - // Otherwise, check the original and alt timecodes. - - if ( ! orgTimeString.empty() ) { - std::string xmpString; - this->xmpObj.GetStructField ( kXMP_NS_DM, kStartTimecode, kXMP_NS_DM, kTimeValue, &xmpString, 0 ); - if (xmpString.compare ( 0, REALTIMELEN, orgTimeString, 0, REALTIMELEN ) ) { - this->xmpObj.SetStructField ( kXMP_NS_DM, kStartTimecode, kXMP_NS_DM, kTimeValue, orgTimeString, 0 ); - this->containsXMP = true; - } - } - - if ( ! altTimeString.empty() ) { - std::string xmpString; - this->xmpObj.GetStructField ( kXMP_NS_DM, kAltTimecode, kXMP_NS_DM, kTimeValue, &xmpString, 0 ); - if ( xmpString.compare ( 0, REALTIMELEN, altTimeString, 0, REALTIMELEN ) ) { - this->xmpObj.SetStructField ( kXMP_NS_DM, kAltTimecode, kXMP_NS_DM, kTimeValue, altTimeString, 0 ); - this->containsXMP = true; - } - } - - } - - unsigned long orgReelSize; - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, myOrgReelChunk, myTimeList, 0, 0, &orgReelSize ); - if ( ok ) { - - std::string orgReelString; - orgReelString.reserve ( orgReelSize ); - orgReelString.assign ( orgReelSize, ' ' ); - RIFF_Support::GetRIFFChunk ( fileRef, riffState, myOrgReelChunk, myTimeList, 0, (char*)orgReelString.c_str(), &orgReelSize ); - - if ( ! orgReelString.empty() ) { - std::string xmpString; - this->xmpObj.GetProperty ( kXMP_NS_DM, kTapeName, &xmpString, 0 ); - if ( xmpString.compare ( 0, REELLEN, orgReelString, 0, REELLEN ) ) { - this->xmpObj.SetProperty ( kXMP_NS_DM, kTapeName, orgReelString, 0 ); - this->containsXMP = true; - } - } - - } - - unsigned long altReelSize; - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, myAltReelChunk, myTimeList, 0, 0, &altReelSize ); - if ( ok ) { - - std::string altReelString; - altReelString.reserve ( altReelSize ); - altReelString.assign ( altReelSize, ' ' ); - RIFF_Support::GetRIFFChunk ( fileRef, riffState, myAltReelChunk, myTimeList, 0, (char*)altReelString.c_str(), &altReelSize ); - - if ( ! altReelString.empty() ) { - std::string xmpString; - this->xmpObj.GetProperty ( kXMP_NS_DM, kAltTapeName, &xmpString, 0 ); - if ( xmpString.compare ( 0, REELLEN, altReelString, 0, REELLEN ) ) { - this->xmpObj.SetProperty ( kXMP_NS_DM, kAltTapeName, altReelString, 0 ); - this->containsXMP = true; - } - } - - } - - unsigned long logCommentSize; - ok = RIFF_Support::GetRIFFChunk ( fileRef, riffState, myCommentChunk, myCommentList, 0, 0, &logCommentSize ); - if ( ok ) { - - std::string logCommentString; - logCommentString.reserve ( logCommentSize ); - logCommentString.assign ( logCommentSize, ' ' ); - RIFF_Support::GetRIFFChunk ( fileRef, riffState, myCommentChunk, myCommentList, 0, (char*)logCommentString.c_str(), &logCommentSize ); - - if ( ! logCommentString.empty() ) { - std::string xmpString; - this->xmpObj.GetProperty ( kXMP_NS_DM, kLogComment, &xmpString, 0 ); - if ( xmpString.compare ( logCommentString ) ) { - this->xmpObj.SetProperty ( kXMP_NS_DM, kLogComment, logCommentString, 0 ); - this->containsXMP = true; - } - } - - } - - CreatorAtom::Import ( this->xmpObj, fileRef, riffState ); - - //// Update the xmpPacket, as the xmpObj might have been updated with legacy info. - //// Produce packet of same size [1781657] - //try { - // this->xmpObj.SerializeToBuffer ( &this->xmpPacket, - // (kXMP_UseCompactFormat | kXMP_ExactPacketLength) , packetInfo.length ); - //} catch ( XMP_Error ) { - // this->xmpObj.SerializeToBuffer ( &this->xmpPacket, (kXMP_UseCompactFormat ) ); - //} - - // removed for [1781657] this->packetInfo.offset = kXMPFiles_UnknownOffset; - // removed for [1781657] this->packetInfo.length = (XMP_StringLen)this->xmpPacket.size(); - this->processedXMP = this->containsXMP; - -} // AVI_MetaHandler::CacheFileData |