Menu

EXC_BAD_ACCESS deep below CAAFMob::CloneExter

Help
Ralph Hill
2010-10-05
2013-04-29
  • Ralph Hill

    Ralph Hill - 2010-10-05

    I have recently switched to a more recent version of the AAFSDK. I was using a version that claimed to be "Version 1.1 Release".  I have switched to a version that claims to be "Version 1.1.3 Release".  I am building under a Mac  OS 10.5.8 with Intel processor. All my users run 10.5.8 or 10.6.4 on Intel processors.

    Under the old SDK things generally ran great.  I recently upgraded to the new version and things ran great, without changes to my apps, except one app that attempts to construct an AAF file with a single composition and no embedded media. This app is based on sample code I received from Avid about 2 years ago.  It has been working without a hitch for about a year.

    Here is a stack trace showing what happens now.  This is happening on the second call to CloneExternal.  So, I am thinking that the first call to CloneExternal may be leaving things in a bad state. The failure is the same with different data sets and is completely repeatable.

    Is there anyone who understands this part of the code who has time to help track this down? It is failing 23 calls deep into code I have, but have never looked at. If someone has the time to help me with this, I can build a sample app that demonstrates the problem and find some sample data that I can share.

    Here is a stack trace.

    #0 0x92868a03 in __dynamic_cast
    #1 0x01c51a89 in OMWeakReferenceProperty<OMObjectIdentification, ImplAAFTypeDef>::getValue at OMWeakRefPropertyT.h:135
    #2 0x01b5073e in OMWeakReferenceProperty<OMObjectIdentification, ImplAAFTypeDef>::operator ImplAAFTypeDef* at OMWeakRefPropertyT.h:259
    #3 0x01b561fd in ImplAAFMetaDefinition::bootstrapTypeWeakReference at ImplAAFMetaDefinition.cpp:299
    #4 0x01c3315a in ImplAAFTypeDefVariableArray::GetType at ImplAAFTypeDefVariableArry.cpp:113
    #5 0x01c313de in ImplAAFTypeDefVariableArray::BaseType at ImplAAFTypeDefVariableArry.cpp:374
    #6 0x01c33244 in ImplAAFTypeDefVariableArray::pvtCreateOMProperty at ImplAAFTypeDefVariableArry.cpp:621
    #7 0x01bb9c58 in ImplAAFPropertyDef::CreateOMProperty at ImplAAFPropertyDef.cpp:362
    #8 0x01b8c89e in ImplAAFObject::InitOMProperty at ImplAAFObject.cpp:1303
    #9 0x01b8d0c3 in ImplAAFObject::InitOMProperties at ImplAAFObject.cpp:1247
    #10 0x01b8cfb8 in ImplAAFObject::InitOMProperties at ImplAAFObject.cpp:1230
    #11 0x01b8cfb8 in ImplAAFObject::InitOMProperties at ImplAAFObject.cpp:1230
    #12 0x01b8cfb8 in ImplAAFObject::InitOMProperties at ImplAAFObject.cpp:1230
    #13 0x01bd8b25 in ImplAAFStorable::InitializeOMStorable at ImplAAFStorable.cpp:72
    #14 0x01af7cf4 in ImplAAFDictionary::CreateAndInit at ImplAAFDictionary.cpp:419
    #15 0x01af7db6 in ImplAAFDictionary::CreateInstance at ImplAAFDictionary.cpp:550
    #16 0x01af3402 in ImplAAFDictionary::create at ImplAAFDictionary.cpp:374
    #17 0x01cdf8e3 in OMStorable::shallowCopy at OMStorable.cpp:486
    #18 0x01bd7713 in OMStrongReferenceProperty<ImplAAFEssenceDescriptor>::deepCopyTo at OMStrongRefPropertyT.h:491
    #19 0x01cdf80b in OMStorable::deepCopyTo at OMStorable.cpp:530
    #20 0x01b79e1c in ImplAAFMob::CloneExternal at ImplAAFMob.cpp:1690
    #21 0x01b7925e in ImplAAFMob::CloneDependencies at ImplAAFMob.cpp:2473
    #22 0x01b79ed4 in ImplAAFMob::CloneExternal at ImplAAFMob.cpp:1702
    #23 0x01a1e356 in CAAFMob::CloneExternal at CAAFMob.cpp:1755
    #24 0x00005eff in _AddMobsForOneFile at aafMakeComposition.cpp:578
    #25 0x0000724e in _AddShot at aafMakeComposition.cpp:436
    #26 0x00007ae8 in _AddShots at aafMakeComposition.cpp:269
    #27 0x00008d8a in main at aafMakeComposition.cpp:190

    Here is my method that is calling CloneExternal.  It gets called once for each AAF file in a list. Each of those AAF files has a video track and possibly an audio track. The goal is to build up a composition mob that references the video from each of the input AAF files.

    static void
    _AddMobsForOneFile(const string& inFileName,
                       aafPosition_t startFrame,
                       aafLength_t duration,
                       aafRational_t editRate,
                       IAAFMob* outMob,
                       IAAFFile* outFile)
    {
        aafMobID_t masterMobID;
        aafLength_t componentLength;
        IAAFFileSP inFile;
        IAAFMobSP inPrimaryMob;
        IAAFSegmentSP       sourceClipSeg;
        IAAFComponentSP sourceClipComponent;
        IAAFSequenceSP destSequence;
       
        char* ext = strrchr(inFileName.c_str(), '.');
        if ((ext == NULL) || (strcmp(ext, ".mxf") != 0) && strcmp(ext, ".aaf") != 0) {
            fprintf(stderr, "Media files in playlist must be MXF or AAF files. %s appears to be something else.\n", inFileName.c_str());
            exit(1);
        }
       
        wchar_t* wideInFileName = new wchar_t;
        mbstowcs(wideInFileName, inFileName.c_str(), inFileName.length()+1);
        AAFCheck(AAFFileOpenExistingRead(wideInFileName,  0, &inFile));
        delete  wideInFileName;
       
        IAAFHeaderSP inHeader;
        AAFCheck(inFile->GetHeader(&inHeader));
        IAAFDictionarySP pDictionary;
        AAFCheck(inHeader->GetDictionary(&pDictionary));
        IAAFHeaderSP outHeader;
        AAFCheck(outFile->GetHeader(&outHeader));
        IAAFDictionarySP outDictionary;
        AAFCheck(outHeader->GetDictionary(&outDictionary));
        IAAFClassDefSP fillerDef;
        AAFCheck(outDictionary->LookupClassDef(AUID_AAFFiller, &fillerDef));
       
        aafSearchCrit_t criteria;
        criteria.searchTag = kAAFByMobKind;
        criteria.tags.mobKind = kAAFMasterMob;
        IEnumAAFMobs* mobs;
        AAFCheck(inHeader->GetMobs(&criteria, &mobs));
        if (mobs->NextOne(&inPrimaryMob) == 0) {
            aafSlotID_t slotID;
            aafSlotID_t         destSlotID;
            IAAFMobSlotSP inSlot;
            IAAFSegmentSP inSegment;
            IAAFComponentSP inComponent;
            IAAFDataDef* outDataDef;
           
            aafUInt32 physSlot = INT_MAX;
           
            BOOL wroteVideo = false;
            BOOL wroteA1 = false;
                   
            AAFCheck(inPrimaryMob->GetMobID(&masterMobID)); // Overwrite previous value
            IEnumAAFMobSlotsSP slots;
            AAFCheck(inPrimaryMob->GetSlots(&slots));
            while (slots->NextOne(&inSlot) == 0) {
                IAAFDataDef* dataDef;
                AAFCheck(inSlot->GetDataDef(&dataDef));
                aafBoolean_t isPicture;
                AAFCheck(dataDef->IsPictureKind(&isPicture));
                aafBoolean_t isSound;
                AAFCheck(dataDef->IsSoundKind(&isSound));
               
                AAFCheck(inSlot->GetPhysicalNum(&physSlot));
               
                // hard wire to write video and A1 for  now.
                const BOOL doWriteVideo = isPicture;
                // no audio tracks for now.
                const BOOL doWriteA1 = FALSE; // was:  isSound && (physSlot == A1_PHYS_CH);
                if (doWriteVideo || doWriteA1) {
                    if (doWriteVideo) {
                        wroteVideo = true;
                        destSlotID = V_SLOTID;
                    }
                    // XXX should probably deal with audio as an array of tracks.
                    if (doWriteA1) {
                        wroteA1 = true;
                        destSlotID = A1_SLOTID;
                    }
                    AAFCheck(inSlot->GetSegment(&inSegment));
                    AAFCheck(inSlot->GetSlotID(&slotID));
                    AAFCheck(inSegment->QueryInterface( IID_IAAFComponent, (void**)&inComponent ));
                    AAFCheck(inComponent->GetLength(&componentLength));
                   
                    if(isPicture) {
                        AAFCheck(outDictionary->LookupDataDef(kAAFDataDef_Picture, &outDataDef));
                    } else {
                        AAFCheck(outDictionary->LookupDataDef(kAAFDataDef_Sound, &outDataDef));
                    }
                   
                    _CreateSequenceIfNeeded(outHeader, outMob, outDataDef, editRate, slotID, physSlot, &destSequence);
                   
                    if(duration == -1)
                        duration = componentLength - startFrame;
                   
                    CreateSourceClip(outHeader, outDataDef, masterMobID,slotID, startFrame, duration, &sourceClipSeg);
                    AAFCheck(sourceClipSeg->QueryInterface( IID_IAAFComponent, (void**)&sourceClipComponent ));
                    AAFCheck(destSequence->AppendComponent(sourceClipComponent));
                    outDataDef->Release();
                }
               
                dataDef->Release();
            }
           
            if (!wroteVideo) {
                IAAFDataDefSP pictureDef;
                IAAFComponentSP fillerComponent;
                IAAFFillerSP filler;
                IAAFSequenceSP destSequence;
               
                AAFCheck(outDictionary->LookupDataDef(kAAFDataDef_Picture, &pictureDef));
                _CreateSequenceIfNeeded(outHeader, outMob, pictureDef, editRate, V_SLOTID, V_PHYS_CH, &destSequence);
                AAFCheck(fillerDef->CreateInstance(IID_IAAFFiller, (IUnknown **)&filler));
                AAFCheck(filler->Initialize(pictureDef, duration));
                AAFCheck(filler->QueryInterface(IID_IAAFComponent, (void**)&fillerComponent));
                AAFCheck(destSequence->AppendComponent(fillerComponent));
            }
           
            AAFCheck(inPrimaryMob->CloneExternal(kAAFFollowDepend, kAAFNoIncludeMedia, outFile, &outMob));
            mobs->Release();
            inFile->Close();
        } else {
            printf("No clips in file '%s'\n", inFileName.c_str());
            exit(1);
        }       
    }

     
  • Philip de Nier

    Philip de Nier - 2010-10-06

    Send me a sample app and data and I'll see whether I can track down the problem.

    A dump of the input AAF files (InfoDumper -meta …)  would be useful to start with as it might help to identify the variable array property in the essence descriptor that is being cloned.

    Philip

     
  • Ralph Hill

    Ralph Hill - 2010-10-06

    Thanks Philip.  I will start working on a simple sample app right away.  I should have something ready tomorrow.  What is the easiest way to send it and the sample data to you?

    I can send you the output of InfoDumper for the first few files anytime.  How should I send it? It is about 2200 lines, 87k bytes per input file.

     
  • Philip de Nier

    Philip de Nier - 2010-10-07

    Email the InfoDumper dumps to "philipn@users.sourceforge.net" and if the sample data is too large for email then I can give you an ftp address to use.

    Philip

     
  • Philip de Nier

    Philip de Nier - 2010-10-13

    Just to conclude this thread, there was a bug in the cloning code - see explanation below.

    Philip

    The property causing the problem is EssenceDescriptor::SubDescriptors.
    This property was removed from the SDK about 14 months ago.

    Your sample AAF files included this property definition in the
    meta-dictionary because it was created using an older SDK. Cloning the
    Mob from one AAF file to another resulted in the
    EssenceDescriptor::SubDescriptors property definition and associated
    type definitions being cloned.

    This exposed a bug in the cloning code. The cloning code is storing
    references to objects from the input file and it should be storing
    references to objects in the output file or leaving them unresolved. The
    result is that those references become invalid when the input file is
    deleted (ie. when _AddMobsForOneFile ends). This becomes an issue when
    you run _AddMobsForOneFile the second time because it tries to
    dereference and dynamic_cast an invalid value.

     

Log in to post a comment.