2017-04-11 24 views
0

mp4 컨테이너에 XMP 메타 데이터를 읽고 주입해야합니다.iOS - mp4 비디오의 XMP 메타 데이터 읽기/쓰기

"mp4parser"라이브러리로 안드로이드에서 가능하다는 것을 알고 있지만, iOS에 해당하는 것을 찾을 수 없습니다.

읽기 부분의 경우 카메라 롤에서 모든 영상을 읽어 360 XMP 메타 데이터를 신속하게 검사 할 수 있습니까?

필자는 Adobe의 XMP 툴킷을 사용하려고합니다. 폴더에 mp4 비디오가 있는데 360 메타 데이터를 주입하고 싶습니다.

메타 데이터를 삽입 한 후에 (비디오라고 생각합니다) 카메라 롤로 비디오를 내보내지만 비디오가 m4v로 변환되어 작성한 모든 메타 데이터가 손실 된 것처럼 보입니다. 그것은 기대 되는가, 또는 나의 코드가 틀린가? 어떤 도움을 주시면 감사하겠습니다

#import "MetadataManager.h" 

#define IOS_ENV 1 

#include <string> 
#define TXMP_STRING_TYPE std::string 

#define XMP_INCLUDE_XMPFILES 1 
#include "XMP.incl_cpp" 

#include "XMP.hpp" 

#include <iostream> 
#include <fstream> 
using namespace std; 

@implementation MetadataManager { 

} 

+ (void)write360Metadatas:(NSString *)filePath { 


    if (!SXMPMeta::Initialize()) 
     exit(1); 
    if (!SXMPFiles::Initialize()) 
     exit(1); 

    SXMPFiles myFile; 

    XMP_OptionBits opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler; 

    std::string status = ""; 

    std::string filePathStd = std::string([filePath UTF8String]); 

    // First, try to open the file 
    bool ok = myFile.OpenFile(filePathStd, kXMP_UnknownFile, opts); 
    if(! ok){ 
     status += "No smart handler available for " + filePathStd + "\n"; 
     status += "Trying packet scanning.\n"; 
     // Now try using packet scanning 
     opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning; 
     ok = myFile.OpenFile(filePathStd, kXMP_UnknownFile, opts); 
    } 

    if(ok){ 
     SXMPMeta meta; 
     myFile.GetXMP(&meta); 

     displayPropertyValues(&meta); 
     injectMetadatas(&meta); 

     // Check we can put the XMP packet back into the file 
     if(myFile.CanPutXMP(meta)) 
     { 
      // If so then update the file with the modified XMP 
      myFile.PutXMP(meta); 
     } 

     // Close the SXMPFile. This *must* be called. The XMP is not 
     // actually written and the disk file is not closed until this call is made. 
     myFile.CloseFile(); 
    } 
} 

SXMPMeta createXMPFromRDF() 
{ 
    const char * rdf = 
    "<rdf:SphericalVideo xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'" 
    " xmlns:GSpherical='http://ns.google.com/videos/1.0/spherical/'>" 
    "<GSpherical:Spherical>true</GSpherical:Spherical>" 
    "<GSpherical:Stitched>true</GSpherical:Stitched>" 
    "<GSpherical:StitchingSoftware>Spherical Metadata Tool</GSpherical:StitchingSoftware>" 
    "<GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType>" 
    "</rdf:SphericalVideo>"; 

    SXMPMeta meta; 
    // Loop over the rdf string and create the XMP object 
    // 10 characters at a time 
    int i; 
    for (i = 0; i < (long)strlen(rdf) - 10; i += 10) 
    { 
     meta.ParseFromBuffer (&rdf[i], 10, kXMP_ParseMoreBuffers); 
    } 

    // The last call has no kXMP_ParseMoreBuffers options, signifying 
    // this is the last input buffer 
    meta.ParseFromBuffer (&rdf[i], (XMP_StringLen) strlen(rdf) - i); 
    return meta; 

} 


void injectMetadatas(SXMPMeta * meta) 
{ 
    // Add an item onto the dc:creator array 
    // Note the options used, kXMP_PropArrayIsOrdered, if the array does not exist it will be created 
    meta->AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Author Name", 0); 
    meta->AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Another Author Name", 0); 

    // Now update alt-text properties 
    meta->SetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", "An English title"); 
    meta->SetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", "Un titre Francais"); 

    // Display the properties again to show changes 
    cout << "After update:" << endl; 
    displayPropertyValues(meta); 

    // Create a new XMP object from an RDF string 
       SXMPMeta rdfMeta = createXMPFromRDF(); 

       // Append the newly created properties onto the original XMP object 
       // This will: 
       // a) Add ANY new TOP LEVEL properties in the source (rdfMeta) to the destination (meta) 
       // b) Replace any top level properties in the source with the matching properties from the destination 
       SXMPUtils::ApplyTemplate(meta, rdfMeta, kXMPTemplate_AddNewProperties | kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties); 

       // Display the properties again to show changes 
       cout << "After Appending Properties:" << endl; 
       displayPropertyValues(meta); 


} 
void displayPropertyValues(SXMPMeta * meta) 
{ 
    // Read a simple property 
    string simpleValue; //Stores the value for the property 
    meta->GetProperty(kXMP_NS_XMP, "CreatorTool", &simpleValue, 0); 
    cout << "meta:CreatorTool = " << simpleValue << endl; 

    // Get the first and second element in the dc:creator array 
    string elementValue; 
    meta->GetArrayItem(kXMP_NS_DC, "creator", 1, &elementValue, 0); 
    if(elementValue != "") 
    { 
     cout << "dc:creator[1] = " << elementValue << endl; 
     meta->GetArrayItem(kXMP_NS_DC, "creator", 2, &elementValue, 0); 
     cout << "dc:creator[2] = " << elementValue << endl; 
    } 

    // Get the the entire dc:subject array 
    string propValue; 
    int arrSize = meta->CountArrayItems(kXMP_NS_DC, "subject"); 
    for(int i = 1; i <= arrSize;i++) 
    { 
     meta->GetArrayItem(kXMP_NS_DC, "subject", i, &propValue, 0); 
     cout << "dc:subject[" << i << "] = " << propValue << endl; 
    } 

    // Get the dc:title for English and French 
    string itemValue; 
    string actualLang; 
    meta->GetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", 0, &itemValue, 0); 
    cout << "dc:title in English = " << itemValue << endl; 

    meta->GetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", 0, &itemValue, 0); 
    cout << "dc:title in French = " << itemValue << endl; 

    // Get dc:MetadataDate 
    XMP_DateTime myDate; 
    if(meta->GetProperty_Date(kXMP_NS_XMP, "MetadataDate", &myDate, 0)) 
    { 
     // Convert the date struct into a convenient string and display it 
     string myDateStr; 
     SXMPUtils::ConvertFromDate(myDate, &myDateStr); 
     cout << "meta:MetadataDate = " << myDateStr << endl;       
    } 

    cout << "----------------------------------------" << endl; 
} 

@end 

MetadataManager.mm, 감사 :

여기에 코드입니다.

답변