/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license that can
* be found in the License.html file in the root of the source tree.
*/
//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_DCP_YES)
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_DcpAm.h"
#include "MediaInfo/MediaInfo.h"
#include "MediaInfo/MediaInfo_Internal.h"
#include "MediaInfo/Multiple/File__ReferenceFilesHelper.h"
#include "MediaInfo/Multiple/File_DcpCpl.h"
#include "MediaInfo/XmlUtils.h"
#include "ZenLib/FileName.h"
#include "tinyxml2.h"
using namespace tinyxml2;
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
//---------------------------------------------------------------------------
File_DcpAm::File_DcpAm()
:File__Analyze(), File__HasReferences()
{
#if MEDIAINFO_EVENTS
ParserIDs[0]=MediaInfo_Parser_DcpAm;
StreamIDs_Width[0]=sizeof(size_t)*2;
#endif //MEDIAINFO_EVENTS
#if MEDIAINFO_DEMUX
Demux_EventWasSent_Accept_Specific=true;
#endif //MEDIAINFO_DEMUX
//PKL
PKL_Pos=(size_t)-1;
}
//***************************************************************************
// Streams management
//***************************************************************************
//---------------------------------------------------------------------------
void File_DcpAm::Streams_Finish()
{
ReferenceFiles_Finish();
// Detection of IMF CPL
bool IsImf=false;
for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
if (Retrieve((stream_t)StreamKind, StreamPos, "MuxingMode").find(__T("IMF CPL"))==0)
IsImf=true;
if (IsImf)
{
Fill(Stream_General, 0, General_Format, "IMF AM", Unlimited, true, true);
Clear(Stream_General, 0, General_Format_Version);
}
}
//***************************************************************************
// Buffer - File header
//***************************************************************************
//---------------------------------------------------------------------------
bool File_DcpAm::FileHeader_Begin()
{
static const char *InteropNs="http://www.digicine.com/PROTO-ASDCP-AM-20040311#";
static const char *SmpteNs="http://www.smpte-ra.org/schemas/429-9/2007/AM";
XMLDocument document;
if (!FileHeader_Begin_XML(document))
return false;
XMLElement* AssetMap=document.FirstChildElement();
const char *NameSpace;
if (!AssetMap || strcmp(LocalName(AssetMap, NameSpace), "AssetMap") || !NameSpace)
{
Reject("DcpAm");
return false;
}
std::string FmtVersion;
if (!strcmp(NameSpace, InteropNs))
{
FmtVersion="Interop";
}
else if (!strcmp(NameSpace, SmpteNs))
{
FmtVersion="SMPTE";
}
else
{
Reject("DcpAm");
return false;
}
Accept("DcpAm");
Fill(Stream_General, 0, General_Format, "DCP AM");
Fill(Stream_General, 0, General_Format_Version, FmtVersion);
#if defined(MEDIAINFO_REFERENCES_YES)
Config->File_ID_OnlyRoot_Set(false);
ReferenceFiles_Accept(this, Config);
//Parsing main elements
for (XMLElement* AssetMap_Item=AssetMap->FirstChildElement(); AssetMap_Item; AssetMap_Item=AssetMap_Item->NextSiblingElement())
{
const char *AmItemNs, *AmItemName = LocalName(AssetMap_Item, AmItemNs);
if (!AmItemNs || strcmp(AmItemNs, NameSpace))
continue; // item has wrong namespace
//AssetList
if (!strcmp(AmItemName, "AssetList"))
{
for (XMLElement* AssetList_Item=AssetMap_Item->FirstChildElement(); AssetList_Item; AssetList_Item=AssetList_Item->NextSiblingElement())
{
//Asset
if (MatchQName(AssetList_Item, "Asset", NameSpace))
{
File_DcpPkl::stream Stream;
for (XMLElement* Asset_Item=AssetList_Item->FirstChildElement(); Asset_Item; Asset_Item=Asset_Item->NextSiblingElement())
{
//ChunkList
if (MatchQName(Asset_Item, "ChunkList", NameSpace))
{
for (XMLElement* ChunkList_Item=Asset_Item->FirstChildElement(); ChunkList_Item; ChunkList_Item=ChunkList_Item->NextSiblingElement())
{
//Chunk
if (MatchQName(ChunkList_Item, "Chunk", NameSpace))
{
File_DcpPkl::stream::chunk Chunk;
for (XMLElement* Chunk_Item=ChunkList_Item->FirstChildElement(); Chunk_Item; Chunk_Item=Chunk_Item->NextSiblingElement())
{
//Path
if (MatchQName(Chunk_Item, "Path", NameSpace))
if (const char* Text=Chunk_Item->GetText())
Chunk.Path=Text;
}
Stream.ChunkList.push_back(Chunk);
}
}
}
//Id
if (MatchQName(Asset_Item, "Id", NameSpace))
if (const char* Text=Asset_Item->GetText())
Stream.Id=Text;
//PackingList
if (MatchQName(Asset_Item, "PackingList", NameSpace) &&
Asset_Item->GetText() && !strcmp(Asset_Item->GetText(), "true"))
{
PKL_Pos=Streams.size();
Stream.StreamKind=(stream_t)(Stream_Max+2); // Means PKL
}
}
Streams.push_back(Stream);
}
}
}
//Creator
if (!strcmp(AmItemName, "Creator"))
Fill(Stream_General, 0, General_Encoded_Library, AssetMap_Item->GetText());
//IssueDate
if (!strcmp(AmItemName, "IssueDate"))
Fill(Stream_General, 0, General_Encoded_Date, AssetMap_Item->GetText());
//Issuer
if (!strcmp(AmItemName, "Issuer"))
Fill(Stream_General, 0, General_EncodedBy, AssetMap_Item->GetText());
}
//Merging with PKL
if (PKL_Pos<Streams.size() && Streams[PKL_Pos].ChunkList.size()==1)
{
FileName Directory(File_Name);
Ztring PKL_FileName; PKL_FileName.From_UTF8(Streams[PKL_Pos].ChunkList[0].Path);
if (PKL_FileName.find(__T("file://"))==0 && PKL_FileName.find(__T("file:///"))==string::npos)
PKL_FileName.erase(0, 7); //TODO: better handling of relative and absolute file naes
MediaInfo_Internal MI;
MI.Option(__T("File_KeepInfo"), __T("1"));
Ztring ParseSpeed_Save=MI.Option(__T("ParseSpeed_Get"), __T(""));
Ztring Demux_Save=MI.Option(__T("Demux_Get"), __T(""));
MI.Option(__T("ParseSpeed"), __T("0"));
MI.Option(__T("Demux"), Ztring());
MI.Option(__T("File_IsReferenced"), __T("1"));
Ztring DirPath = Directory.Path_Get();
if (!DirPath.empty())
DirPath += PathSeparator;
size_t MiOpenResult=MI.Open(DirPath+PKL_FileName);
MI.Option(__T("ParseSpeed"), ParseSpeed_Save); //This is a global value, need to reset it. TODO: local value
MI.Option(__T("Demux"), Demux_Save); //This is a global value, need to reset it. TODO: local value
if (MiOpenResult
&& (MI.Get(Stream_General, 0, General_Format)==__T("DCP PKL")
|| MI.Get(Stream_General, 0, General_Format)==__T("IMF PKL")))
{
MergeFromPkl(((File_DcpPkl*)MI.Info)->Streams);
for (size_t Pos=0; Pos<MI.Count_Get(Stream_Other); ++Pos)
{
Stream_Prepare(Stream_Other);
Merge(*MI.Info, Stream_Other, Pos, StreamPos_Last);
}
}
}
//Creating the playlist
if (!Config->File_IsReferenced_Get())
{
for (File_DcpPkl::streams::iterator Stream=Streams.begin(); Stream!=Streams.end(); ++Stream)
if (Stream->StreamKind==(stream_t)(Stream_Max+1) && Stream->ChunkList.size()==1) // Means CPL
{
sequence* Sequence=new sequence;
Sequence->FileNames.push_back(Ztring().From_UTF8(Stream->ChunkList[0].Path));
Sequence->StreamID=ReferenceFiles->Sequences_Size()+1;
ReferenceFiles->AddSequence(Sequence);
}
ReferenceFiles->FilesForStorage=true;
}
#endif //MEDIAINFO_REFERENCES_YES
//All should be OK...
Element_Offset=File_Size;
return true;
}
//***************************************************************************
// Infos
//***************************************************************************
//---------------------------------------------------------------------------
void File_DcpAm::MergeFromPkl (File_DcpPkl::streams &StreamsToMerge)
{
for (File_DcpPkl::streams::iterator Stream=Streams.begin(); Stream!=Streams.end(); ++Stream)
{
for (File_DcpPkl::streams::iterator StreamToMerge=StreamsToMerge.begin(); StreamToMerge!=StreamsToMerge.end(); ++StreamToMerge)
if (StreamToMerge->Id==Stream->Id)
{
if (Stream->StreamKind==Stream_Max)
Stream->StreamKind=StreamToMerge->StreamKind;
if (Stream->OriginalFileName.empty())
Stream->OriginalFileName=StreamToMerge->OriginalFileName;
if (Stream->Type.empty())
Stream->Type=StreamToMerge->Type;
if (Stream->AnnotationText.empty())
Stream->AnnotationText=StreamToMerge->AnnotationText;
}
}
}
} //NameSpace
#endif //MEDIAINFO_DCP_YES
↑ V688 The 'Stream' local variable possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'Stream' local variable possesses the same name as one of the class members, which can result in a confusion.
↑ V526 The 'strcmp' function returns 0 if corresponding strings are equal. Consider examining the condition for mistakes.
↑ V526 The 'strcmp' function returns 0 if corresponding strings are equal. Consider examining the condition for mistakes.
↑ V688 The 'Stream' local variable possesses the same name as one of the class members, which can result in a confusion.