Пример #1
0
bool
genericSetItem( MP4File& file, const MP4ItmfItem* item )
{
    if( !item || !item->__handle )
        return false;

    MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" );
    if( !ilst )
        return false;

    MP4ItemAtom* const old = static_cast<MP4ItemAtom*>(item->__handle);
    const uint32_t childCount = ilst->GetNumberOfChildAtoms();
    uint32_t fidx = numeric_limits<uint32_t>::max();
    for( uint32_t i = 0; i < childCount; i++ ) {
        MP4Atom* atom = ilst->GetChildAtom( i );
        if( atom == old ) {
            fidx = i;
            break;
        }
    }

    if( fidx == numeric_limits<uint32_t>::max() )
        return false;

    ilst->DeleteChildAtom( old );
    delete old;

    MP4ItemAtom& itemAtom = *(MP4ItemAtom*)MP4Atom::CreateAtom( file, ilst, item->code );
    ilst->InsertChildAtom( &itemAtom, fidx );

    return __itemModelToAtom( *item, itemAtom );
}
Пример #2
0
void MP4SoundAtom::Read()
{
  MP4Atom *parent = GetParentAtom();
  if (ATOMID(parent->GetType()) != ATOMID("stsd")) {
    // Quicktime has an interesting thing - they'll put an mp4a atom
    // which is blank inside a wave atom, which is inside an mp4a atom
    // we have a mp4a inside an wave inside an mp4a - delete all properties
    m_pProperties.Delete(8);
    m_pProperties.Delete(7);
    m_pProperties.Delete(6);
    m_pProperties.Delete(5);
    m_pProperties.Delete(4);
    m_pProperties.Delete(3);
    m_pProperties.Delete(2);
    m_pProperties.Delete(1);
    m_pProperties.Delete(0);
    if (ATOMID(GetType()) == ATOMID("alac")) {
      AddProperty(new MP4BytesProperty("decoderConfig", m_size));
      ReadProperties();
    }
    if (m_pChildAtomInfos.Size() > 0) {
      ReadChildAtoms();
    }
  } else {
    ReadProperties(0, 3); // read first 3 properties
    AddProperties(((MP4IntegerProperty *)m_pProperties[2])->GetValue());
    ReadProperties(3); // continue
    if (m_pChildAtomInfos.Size() > 0) {
      ReadChildAtoms();
    }
  }
  Skip();
}
Пример #3
0
void MP4D263Atom::Write()
{
    // Check whether we have valid values in the bitr atom
    // (if it exists, of course)
    MP4Atom* bitrAtom = FindAtom("d263.bitr");
    if (bitrAtom) {
        uint32_t avgBitrate;
        uint32_t maxBitrate;

        MP4Integer32Property* pProp;
        bitrAtom->FindProperty("bitr.avgBitrate",
                               (MP4Property**)&pProp,
                               NULL);
        ASSERT(pProp);
        avgBitrate = pProp->GetValue();

        bitrAtom->FindProperty("bitr.maxBitrate",
                               (MP4Property**)&pProp,
                               NULL);
        ASSERT(pProp);
        maxBitrate = pProp->GetValue();

        if (!maxBitrate && !avgBitrate) {
            DeleteChildAtom(bitrAtom);
        }
    }

    MP4Atom::Write();
}
Пример #4
0
MP4ItmfItemList*
genericGetItemsByCode( MP4File& file, const string& code )
{
    MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" );
    if( !ilst )
        return __itemListAlloc();

    // pass 1: filter by code and populate indexList
    const uint32_t childCount = ilst->GetNumberOfChildAtoms();
    vector<uint32_t> indexList;
    for( uint32_t i = 0; i < childCount; i++ ) {
        if( ATOMID( ilst->GetChildAtom( i )->GetType() ) != ATOMID( code.c_str() ))
            continue;
        indexList.push_back( i );
    }

    if( indexList.size() < 1 )
        return __itemListAlloc();

    MP4ItmfItemList& list = *__itemListAlloc();
    __itemListResize( list, (uint32_t)indexList.size() );

    // pass 2: process each atom
    const vector<uint32_t>::size_type max = indexList.size();
    for( vector<uint32_t>::size_type i = 0; i < max; i++ ) {
        uint32_t& aidx = indexList[i];
        __itemAtomToModel( *(MP4ItemAtom*)ilst->GetChildAtom( aidx ), list.elements[i] );
    }

    return &list;
}
Пример #5
0
void MP4File::Make3GPCompliant(const char* fileName,  char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount, bool deleteIodsAtom)
{
    char brand[5] = "3gp5";
    char* _3gpSupportedBrands[1] = { (char*)&brand };

    if (majorBrand) {
        if (!supportedBrands || !supportedBrandsCount) {
            throw new MP4Error("Invalid parameters", "MP4File::Make3GPCompliant");
        }
    }

    MakeFtypAtom(
        majorBrand ? majorBrand : (char*)brand,
        majorBrand ? minorVersion  : _3GP_MINOR_VERSION,
        majorBrand ? supportedBrands : (char**)_3gpSupportedBrands,
        majorBrand ? supportedBrandsCount : 1);

    if (deleteIodsAtom) {
        // Delete the iods atom, if it exists....
        MP4Atom* iodsAtom = m_pRootAtom->FindAtom("moov.iods");
        if (iodsAtom) {
            MP4Atom* moovAtom = m_pRootAtom->FindAtom("moov");
            ASSERT(moovAtom);

            moovAtom->DeleteChildAtom(iodsAtom);
        }
    }

}
Пример #6
0
void MP4RootAtom::FinishOptimalWrite() 
{
    // finish writing mdat
    m_pChildAtoms[GetLastMdatIndex()]->FinishWrite(m_pFile->Use64Bits("mdat"));

    // find moov atom
    u_int32_t size = m_pChildAtoms.Size();
    MP4Atom* pMoovAtom = NULL;

    u_int32_t i;
    for (i = 0; i < size; i++) {
        if (!strcmp("moov", m_pChildAtoms[i]->GetType())) {
            pMoovAtom = m_pChildAtoms[i];
            break;
        }
    }
    ASSERT(i < size);

    // rewrite moov so that updated chunkOffsets are written to disk
    m_pFile->SetPosition(pMoovAtom->GetStart());
    u_int64_t oldSize = pMoovAtom->GetSize();

    pMoovAtom->Write();

    // sanity check
    u_int64_t newSize = pMoovAtom->GetSize();
    ASSERT(oldSize == newSize);
}
Пример #7
0
void MP4Track::UpdateSyncSamples(MP4SampleId sampleId, bool isSyncSample)
{
	if (isSyncSample) {
		// if stss atom exists, add entry
		if (m_pStssCountProperty) {
			m_pStssSampleProperty->AddValue(sampleId);
			m_pStssCountProperty->IncrementValue();
		} // else nothing to do (yet)

	} else { // !isSyncSample
		// if stss atom doesn't exist, create one
		if (m_pStssCountProperty == NULL) {

			MP4Atom* pStssAtom = AddAtom("trak.mdia.minf.stbl", "stss");

			pStssAtom->FindProperty(
				"stss.entryCount",
				(MP4Property**)&m_pStssCountProperty);

			pStssAtom->FindProperty(
				"stss.entries.sampleNumber",
				(MP4Property**)&m_pStssSampleProperty);

			// set values for all samples that came before this one
			for (MP4SampleId sid = 1; sid < sampleId; sid++) {
				m_pStssSampleProperty->AddValue(sid);
				m_pStssCountProperty->IncrementValue();
			}
		} // else nothing to do
	}
}
Пример #8
0
void MP4Track::UpdateRenderingOffsets(MP4SampleId sampleId, 
	MP4Duration renderingOffset)
{
	// if ctts atom doesn't exist
	if (m_pCttsCountProperty == NULL) {

		// no rendering offset, so nothing to do
		if (renderingOffset == 0) {
			return;
		}

		// else create a ctts atom
		MP4Atom* pCttsAtom = AddAtom("trak.mdia.minf.stbl", "ctts");

		// and get handles on the properties
		pCttsAtom->FindProperty(
			"ctts.entryCount",
			(MP4Property**)&m_pCttsCountProperty);

		pCttsAtom->FindProperty(
			"ctts.entries.sampleCount",
			(MP4Property**)&m_pCttsSampleCountProperty);

		pCttsAtom->FindProperty(
			"ctts.entries.sampleOffset",
			(MP4Property**)&m_pCttsSampleOffsetProperty);

		// if this is not the first sample
		if (sampleId > 1) {
			// add a ctts entry for all previous samples
			// with rendering offset equal to zero
			m_pCttsSampleCountProperty->AddValue(sampleId - 1);
			m_pCttsSampleOffsetProperty->AddValue(0);
			m_pCttsCountProperty->IncrementValue();;
		}
	}

	// ctts atom exists (now)

	u_int32_t numCtts = m_pCttsCountProperty->GetValue();

	// if renderingOffset == renderingOffset of last entry
	if (numCtts && renderingOffset
	   == m_pCttsSampleOffsetProperty->GetValue(numCtts-1)) {

		// increment last entry sampleCount
		m_pCttsSampleCountProperty->IncrementValue(1, numCtts-1);

	} else {
		// add ctts entry, sampleCount = 1, sampleOffset = renderingOffset
		m_pCttsSampleCountProperty->AddValue(1);
		m_pCttsSampleOffsetProperty->AddValue(renderingOffset);
		m_pCttsCountProperty->IncrementValue();
	}
}
Пример #9
0
void MP4HntiAtom::Read() 
{
    MP4Atom* grandParent = m_pParentAtom->GetParentAtom();
    ASSERT(grandParent);
    if (ATOMID(grandParent->GetType()) == ATOMID("trak")) {
        ExpectChildAtom("sdp ", Optional, OnlyOne);
    } else {
        ExpectChildAtom("rtp ", Optional, OnlyOne);
    }

    MP4Atom::Read();
}
Пример #10
0
MP4Atom* MP4Track::AddAtom(char* parentName, char* childName)
{
	MP4Atom* pChildAtom = MP4Atom::CreateAtom(childName);

	MP4Atom* pParentAtom = m_pTrakAtom->FindAtom(parentName);
	ASSERT(pParentAtom);

	pParentAtom->AddChildAtom(pChildAtom);

	pChildAtom->Generate();

	return pChildAtom;
}
Пример #11
0
MP4ItmfItemList*
genericGetItemsByMeaning( MP4File& file, const string& meaning, const string& name )
{
    MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" );
    if( !ilst )
        return __itemListAlloc();

    // pass 1: filter by code and populate indexList
    const uint32_t childCount = ilst->GetNumberOfChildAtoms();
    vector<uint32_t> indexList;
    for( uint32_t i = 0; i < childCount; i++ ) {
        MP4Atom& atom = *ilst->GetChildAtom( i );
        if( ATOMID( atom.GetType() ) != ATOMID( "----" ))
            continue;

        // filter-out meaning mismatch
        MP4MeanAtom* meanAtom = (MP4MeanAtom*)atom.FindAtom( "----.mean" );
        if( !meanAtom )
            continue;
        if( meanAtom->value.CompareToString( meaning ))
            continue;

        if( !name.empty() ) {
            // filter-out name mismatch
            MP4MeanAtom* nameAtom = (MP4MeanAtom*)atom.FindAtom( "----.name" );
            if( !nameAtom )
                continue;
            if( nameAtom->value.CompareToString( name ))
                continue;
        }

        indexList.push_back( i );
    }

    if( indexList.size() < 1 )
        return __itemListAlloc();

    MP4ItmfItemList& list = *__itemListAlloc();
    __itemListResize( list, (uint32_t)indexList.size() );

    // pass 2: process each atom
    const vector<uint32_t>::size_type max = indexList.size();
    for( vector<uint32_t>::size_type i = 0; i < max; i++ ) {
        uint32_t& aidx = indexList[i];
        __itemAtomToModel( *(MP4ItemAtom*)ilst->GetChildAtom( aidx ), list.elements[i] );
    }

    return &list;
}
Пример #12
0
void MP4Meta2Atom::Read ()
{
  MP4Atom *parent = GetParentAtom();
  if (ATOMID(parent->GetType()) == ATOMID("udta")) {
    // add data property
    AddReserved("reserved2", 4); /* 0 */

    AddProperty(
        new MP4BytesProperty("metadata")); /* 1 */
    ((MP4BytesProperty*)m_pProperties[1])->SetValueSize(m_size - 4);
  } else {
    ExpectChildAtom("data", Required, OnlyOne);
  }
  MP4Atom::Read();
}
Пример #13
0
bool
genericRemoveItem( MP4File& file, const MP4ItmfItem* item )
{
    if( !item || !item->__handle )
        return false;

    MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" );
    if( !ilst )
        return false;

    MP4ItemAtom* const old = static_cast<MP4ItemAtom*>(item->__handle);
    ilst->DeleteChildAtom( old );
    delete old;

    return true;
}
Пример #14
0
bool
PictureAspectRatioBox::remove( MP4FileHandle file, uint16_t trackIndex )
{
    MP4Atom* coding;
    if( findCoding( file, trackIndex, coding ))
        throw new MP4Exception( "supported coding not found" );

    MP4Atom* pasp;
    if( findPictureAspectRatioBox( file, *coding, pasp ))
        throw new MP4Exception( "pasp-box not found" );

    coding->DeleteChildAtom( pasp );
    delete pasp;

    return false;
}
Пример #15
0
void MP4StblAtom::Generate()
{
    // as usual
    MP4Atom::Generate();

    // but we also need one of the chunk offset atoms
    MP4Atom* pChunkOffsetAtom;
    if (m_File.Use64Bits(GetType())) {
        pChunkOffsetAtom = CreateAtom(m_File, this, "co64");
    } else {
        pChunkOffsetAtom = CreateAtom(m_File, this, "stco");
    }

    AddChildAtom(pChunkOffsetAtom);

    // and ask it to self generate
    pChunkOffsetAtom->Generate();
}
Пример #16
0
bool
genericAddItem( MP4File& file, const MP4ItmfItem* item )
{
    if( !item )
        return false;

    MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" );
    if( !ilst ) {
        file.AddDescendantAtoms( "moov", "udta.meta.ilst" );
        ilst = file.FindAtom( "moov.udta.meta.ilst" );
        ASSERT( ilst );
    }

    MP4ItemAtom& itemAtom = *(MP4ItemAtom*)MP4Atom::CreateAtom( file, ilst, item->code );
    ilst->AddChildAtom( &itemAtom );

    return __itemModelToAtom( *item, itemAtom );
}
Пример #17
0
MP4ItmfItemList*
genericGetItems( MP4File& file )
{
    MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" );
    if( !ilst )
        return __itemListAlloc();

    const uint32_t itemCount = ilst->GetNumberOfChildAtoms();
    if( itemCount < 1 )
        return __itemListAlloc();

    MP4ItmfItemList& list = *__itemListAlloc();
    __itemListResize( list, itemCount );

    for( uint32_t i = 0; i < list.size; i++ )
        __itemAtomToModel( *(MP4ItemAtom*)ilst->GetChildAtom( i ), list.elements[i] );

    return &list;
}
Пример #18
0
bool
fileFetchSummaryInfo( MP4FileHandle file, FileSummaryInfo& info )
{
    if( file == MP4_INVALID_FILE_HANDLE )
        return true;
    MP4File& mp4 = *((MP4File*)file);

    MP4Atom* root = mp4.FindAtom( "" );
    if( !root )
        return true;

    MP4FtypAtom* ftyp = (MP4FtypAtom*)root->FindAtom( "ftyp" );
    if( !ftyp )
        return true;

    info.major_brand   = ftyp->majorBrand.GetValue();
    info.minor_version = ftyp->minorVersion.GetValue();

    const uint32_t cbmax = ftyp->compatibleBrands.GetCount();
    for( uint32_t i = 0; i < cbmax; i++ ) {
        string s = ftyp->compatibleBrands.GetValue( i );

        // remove spaces so brand set is presentable
        string stripped;
        const string::size_type max = s.length();
        for( string::size_type pos = 0; pos < max; pos++ ) {
            if( s[pos] != ' ' )
                stripped += s[pos];
        }

        if( stripped.empty() )
            continue;

        info.compatible_brands.insert( stripped );
    }

    info.nlargesize = 0;
    info.nversion1  = 0;
    info.nspecial   = 0;
    searchFor64bit( *root, info );

    return false;
}
Пример #19
0
void
searchFor64bit( MP4Atom& atom, FileSummaryInfo& info )
{
    const uint32_t max = atom.GetNumberOfChildAtoms();
    for( uint32_t i = 0; i < max; i++ ) {
        MP4Atom& child = *atom.GetChildAtom( i );

        if( child.GetLargesizeMode() )
            info.nlargesize++;

        MP4Integer8Property* version;
        if( child.FindProperty( "version", (MP4Property**)&version ) && version->GetValue() == 1 )
            info.nversion1++;

        if( !strcmp( child.GetType(), "co64" ))
            info.nspecial++;

        searchFor64bit( child, info );
    }
}
Пример #20
0
bool
PictureAspectRatioBox::set( MP4FileHandle file, uint16_t trackIndex, const Item& item )
{
    MP4Atom* coding;
    if( findCoding( file, trackIndex, coding ))
        throw new MP4Exception( "supported coding not found" );

    MP4Atom* pasp;
    if( findPictureAspectRatioBox( file, *coding, pasp ))
        throw new MP4Exception( "pasp-box not found" );

    MP4Integer16Property* hSpacing;
    MP4Integer16Property* vSpacing;

    if( pasp->FindProperty( "pasp.hSpacing", (MP4Property**)&hSpacing ))
        hSpacing->SetValue( item.hSpacing );

    if( pasp->FindProperty( "pasp.vSpacing", (MP4Property**)&vSpacing ))
        vSpacing->SetValue( item.vSpacing );

    return false;
}
Пример #21
0
bool MP4Track::InitEditListProperties()
{
	m_pElstCountProperty = NULL;
	m_pElstMediaTimeProperty = NULL;
	m_pElstDurationProperty = NULL;
	m_pElstRateProperty = NULL;
	m_pElstReservedProperty = NULL;

	MP4Atom* pElstAtom =
		m_pTrakAtom->FindAtom("trak.edts.elst");

	if (!pElstAtom) {
		return false;
	}

	pElstAtom->FindProperty(
		"elst.entryCount",
		(MP4Property**)&m_pElstCountProperty);

	pElstAtom->FindProperty(
		"elst.entries.mediaTime",
		(MP4Property**)&m_pElstMediaTimeProperty);

	pElstAtom->FindProperty(
		"elst.entries.segmentDuration",
		(MP4Property**)&m_pElstDurationProperty);

	pElstAtom->FindProperty(
		"elst.entries.mediaRate",
		(MP4Property**)&m_pElstRateProperty);

	pElstAtom->FindProperty(
		"elst.entries.reserved",
		(MP4Property**)&m_pElstReservedProperty);

	return m_pElstCountProperty
		&& m_pElstMediaTimeProperty
		&& m_pElstDurationProperty
		&& m_pElstRateProperty
		&& m_pElstReservedProperty;
}
Пример #22
0
void MP4File::CreateIsmaIodFromFile(
    MP4TrackId odTrackId,
    MP4TrackId sceneTrackId,
    MP4TrackId audioTrackId,
    MP4TrackId videoTrackId,
    u_int8_t** ppBytes,
    u_int64_t* pNumBytes)
{
    MP4Descriptor* pIod = new MP4IODescriptor();
    pIod->SetTag(MP4IODescrTag);
    pIod->Generate();

    MP4Atom* pIodsAtom = FindAtom("moov.iods");
    ASSERT(pIodsAtom);
    MP4DescriptorProperty* pSrcIod =
        (MP4DescriptorProperty*)pIodsAtom->GetProperty(2);

    CloneIntegerProperty(pIod, pSrcIod, "objectDescriptorId");
    CloneIntegerProperty(pIod, pSrcIod, "ODProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "sceneProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "audioProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "visualProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "graphicsProfileLevelId");

    // mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
    MP4DescriptorProperty* pEsProperty;
    pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
    pEsProperty->SetTags(MP4ESDescrTag);

    MP4IntegerProperty* pSetProperty;
    MP4IntegerProperty* pSceneESID;
    MP4IntegerProperty* pOdESID;

    // OD
    MP4Descriptor* pOdEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pOdEsd->Generate();

    pOdEsd->FindProperty("ESID",
                         (MP4Property**)&pOdESID);

    // we set the OD ESID to a non-zero unique value
    pOdESID->SetValue(m_odTrackId);

    pOdEsd->FindProperty("URLFlag",
                         (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);

    u_int8_t* pBytes;
    u_int64_t numBytes;

    CreateIsmaODUpdateCommandFromFileForStream(
        audioTrackId,
        videoTrackId,
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data =\n"); MP4HexDump(pBytes, numBytes));

    char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);

    char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);

    sprintf(urlBuf,
            "data:application/mpeg4-od-au;base64,%s",
            odCmdBase64);

    MP4StringProperty* pUrlProperty;
    pOdEsd->FindProperty("URL",
                         (MP4Property**)&pUrlProperty);
    pUrlProperty->SetValue(urlBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data URL = \042%s\042\n", urlBuf));

    MP4Free(odCmdBase64);
    odCmdBase64 = NULL;
    MP4Free(pBytes);
    pBytes = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;

    MP4DescriptorProperty* pSrcDcd = NULL;

    // HACK temporarily point to scene decoder config
    FindProperty(MakeTrackName(odTrackId,
                               "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
                 (MP4Property**)&pSrcDcd);
    ASSERT(pSrcDcd);
    MP4Property* pOrgOdEsdProperty =
        pOdEsd->GetProperty(8);
    pOdEsd->SetProperty(8, pSrcDcd);

    // bufferSizeDB needs to be set appropriately
    MP4BitfieldProperty* pBufferSizeProperty = NULL;
    pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
                         (MP4Property**)&pBufferSizeProperty);
    ASSERT(pBufferSizeProperty);
    pBufferSizeProperty->SetValue(numBytes);

    // SL config needs to change from 2 (file) to 1 (null)
    pOdEsd->FindProperty("slConfigDescr.predefined",
                         (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);


    // Scene
    MP4Descriptor* pSceneEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pSceneEsd->Generate();

    pSceneEsd->FindProperty("ESID",
                            (MP4Property**)&pSceneESID);
    // we set the Scene ESID to a non-zero unique value
    pSceneESID->SetValue(sceneTrackId);

    pSceneEsd->FindProperty("URLFlag",
                            (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);

    CreateIsmaSceneCommand(
        MP4_IS_VALID_TRACK_ID(audioTrackId),
        MP4_IS_VALID_TRACK_ID(videoTrackId),
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data =\n"); MP4HexDump(pBytes, numBytes));

    char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);

    urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
    sprintf(urlBuf,
            "data:application/mpeg4-bifs-au;base64,%s",
            sceneCmdBase64);

    pSceneEsd->FindProperty("URL",
                            (MP4Property**)&pUrlProperty);
    pUrlProperty->SetValue(urlBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data URL = \042%s\042\n", urlBuf));

    MP4Free(sceneCmdBase64);
    sceneCmdBase64 = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;
    MP4Free(pBytes);
    pBytes = NULL;

    // HACK temporarily point to scene decoder config
    FindProperty(MakeTrackName(sceneTrackId,
                               "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
                 (MP4Property**)&pSrcDcd);
    ASSERT(pSrcDcd);
    MP4Property* pOrgSceneEsdProperty =
        pSceneEsd->GetProperty(8);
    pSceneEsd->SetProperty(8, pSrcDcd);

    // bufferSizeDB needs to be set
    pBufferSizeProperty = NULL;
    pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
                            (MP4Property**)&pBufferSizeProperty);
    ASSERT(pBufferSizeProperty);
    pBufferSizeProperty->SetValue(numBytes);

    // SL config needs to change from 2 (file) to 1 (null)
    pSceneEsd->FindProperty("slConfigDescr.predefined",
                            (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);


    // finally get the whole thing written to a memory
    pIod->WriteToMemory(this, ppBytes, pNumBytes);


    // now carefully replace esd properties before destroying
    pOdEsd->SetProperty(8, pOrgOdEsdProperty);
    pSceneEsd->SetProperty(8, pOrgSceneEsdProperty);
    pSceneESID->SetValue(0); // restore 0 value
    pOdESID->SetValue(0);

    delete pIod;

    VERBOSE_ISMA(GetVerbosity(),
                 printf("IOD data =\n"); MP4HexDump(*ppBytes, *pNumBytes));
}
Пример #23
0
void MP4File::MakeFtypAtom(char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount)
{
    bool rewriteNeeded = false;
    u_int32_t currentSupportedBrandsCount;
    u_int32_t i;


    MP4Atom* ftypAtom = m_pRootAtom->FindAtom("ftyp");
    if (ftypAtom == NULL) {
        ftypAtom = InsertChildAtom(m_pRootAtom, "ftyp", 0);
    }
    if (majorBrand == NULL)
        return;
    MP4StringProperty* pMajorBrandProperty;
    if (!ftypAtom->FindProperty(
                "ftyp.majorBrand",
                (MP4Property**)&pMajorBrandProperty))
        return;

    pMajorBrandProperty->SetValue(majorBrand);


    MP4Integer32Property* pMinorVersionProperty;
    if (!ftypAtom->FindProperty(
                "ftype.minorVersion",
                (MP4Property**)&pMinorVersionProperty))
        return;

    pMinorVersionProperty->SetValue(minorVersion);

    MP4Integer32Property* pCompatibleBrandsCountProperty;
    if (!ftypAtom->FindProperty(
                "ftyp.compatibleBrandsCount",
                (MP4Property**)&pCompatibleBrandsCountProperty)) return;

    currentSupportedBrandsCount = pCompatibleBrandsCountProperty->GetValue();

    MP4TableProperty* pCompatibleBrandsProperty;
    if (!ftypAtom->FindProperty(
                "ftyp.compatibleBrands",
                (MP4Property**)&pCompatibleBrandsProperty)) return;

    MP4StringProperty* pBrandProperty = (MP4StringProperty*)
                                        pCompatibleBrandsProperty->GetProperty(0);
    ASSERT(pBrandProperty);

    for (i = 0 ; i < ((currentSupportedBrandsCount > supportedBrandsCount) ? supportedBrandsCount : currentSupportedBrandsCount) ; i++) {
        pBrandProperty->SetValue(supportedBrands[i], i);

    }

    if (i < supportedBrandsCount) {
        for ( ; i < supportedBrandsCount ; i++) {
            pBrandProperty->AddValue(supportedBrands[i]);
        }
    }

    if (currentSupportedBrandsCount != supportedBrandsCount) {
        rewriteNeeded = true;
        pBrandProperty->SetCount(supportedBrandsCount);
        pCompatibleBrandsCountProperty->SetReadOnly(false);
        pCompatibleBrandsCountProperty->SetValue(supportedBrandsCount);
        pCompatibleBrandsCountProperty->SetReadOnly(true);
    }

}
Пример #24
0
FILE* MP4Track::GetSampleFile(MP4SampleId sampleId)
{
	u_int32_t stscIndex =
		GetSampleStscIndex(sampleId);

	u_int32_t stsdIndex = 
		m_pStscSampleDescrIndexProperty->GetValue(stscIndex);

	// check if the answer will be the same as last time
	if (m_lastStsdIndex && stsdIndex == m_lastStsdIndex) {
		return m_lastSampleFile;
	}

	MP4Atom* pStsdAtom = 
		m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd");
	ASSERT(pStsdAtom);

	MP4Atom* pStsdEntryAtom = 
		pStsdAtom->GetChildAtom(stsdIndex - 1);
	ASSERT(pStsdEntryAtom);

	MP4Integer16Property* pDrefIndexProperty = NULL;
	pStsdEntryAtom->FindProperty(
		"*.dataReferenceIndex",
		(MP4Property**)&pDrefIndexProperty);
	
	if (pDrefIndexProperty == NULL) {
		throw new MP4Error("invalid stsd entry", "GetSampleFile");
	}

	u_int32_t drefIndex =
		pDrefIndexProperty->GetValue();

	MP4Atom* pDrefAtom =
		m_pTrakAtom->FindAtom("trak.mdia.minf.dinf.dref");
	ASSERT(pDrefAtom);

	MP4Atom* pUrlAtom =
		pDrefAtom->GetChildAtom(drefIndex - 1);
	ASSERT(pUrlAtom);

	FILE* pFile;

	if (pUrlAtom->GetFlags() & 1) {
		pFile = NULL;	// self-contained
	} else {
#ifndef USE_FILE_CALLBACKS
		MP4StringProperty* pLocationProperty = NULL;
		pUrlAtom->FindProperty(
			"*.location", 
			(MP4Property**)&pLocationProperty);
		ASSERT(pLocationProperty);

		const char* url = pLocationProperty->GetValue();

		VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
			printf("dref url = %s\n", url));

		pFile = (FILE*)-1;

		// attempt to open url if it's a file url 
		// currently this is the only thing we understand
		if (!strncmp(url, "file:", 5)) {
			const char* fileName = url + 5;
			if (!strncmp(fileName, "//", 2)) {
				fileName = strchr(fileName + 2, '/');
			}
			if (fileName) {
				pFile = fopen(fileName, "rb");
				if (!pFile) {
					pFile = (FILE*)-1;
				}
			}
		} 
#else
        throw new MP4Error(errno, "Function not supported when using callbacks", "GetSampleFile");
#endif
	}

	if (m_lastSampleFile) {
#ifndef USE_FILE_CALLBACKS
		fclose(m_lastSampleFile);
#else
        throw new MP4Error(errno, "Function not supported when using callbacks", "GetSampleFile");
#endif
	}

	// cache the answer
	m_lastStsdIndex = stsdIndex;
	m_lastSampleFile = pFile;

	return pFile;
}
Пример #25
0
void MP4File::Make3GPCompliant(const char* fileName,  char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount, bool deleteIodsAtom)
{
    char brand[5] = "3gp5";
    char* _3gpSupportedBrands[1] = { (char*)&brand };

    if (majorBrand) {
        if (!supportedBrands || !supportedBrandsCount) {
            throw new MP4Error("Invalid parameters", "MP4File::Make3GPCompliant");
        }
    }

    m_fileName = MP4Stralloc(fileName);
    m_mode = 'r';
    // first load meta-info into memory
    Open("rb");
    ReadFromFile();

    CacheProperties();	// of moov atom

    // now switch over to writing the new file
    MP4Free(m_fileName);
    // create a temporary file
    m_fileName = MP4Stralloc(TempFileName());

    MakeFtypAtom(
        majorBrand ? majorBrand : (char*)brand,
        majorBrand ? minorVersion  : _3GP_MINOR_VERSION,
        majorBrand ? supportedBrands : (char**)_3gpSupportedBrands,
        majorBrand ? supportedBrandsCount : 1);

    if (deleteIodsAtom) {
        // Delete the iods atom, if it exists....
        MP4Atom* iodsAtom = m_pRootAtom->FindAtom("moov.iods");
        if (iodsAtom) {
            MP4Atom* moovAtom = m_pRootAtom->FindAtom("moov");
            ASSERT(moovAtom);

            moovAtom->DeleteChildAtom(iodsAtom);
        }
    }


    FILE* pReadFile = m_pFile;
    m_pFile = NULL;
    m_mode = 'w';

    Open("wb");

    SetIntegerProperty("moov.mvhd.modificationTime",
                       MP4GetAbsTimestamp());

    // writing meta info in the optimal order
    ((MP4RootAtom*)m_pRootAtom)->BeginOptimalWrite();

    // write data in optimal order
    RewriteMdat(pReadFile, m_pFile);

    // finish writing
    ((MP4RootAtom*)m_pRootAtom)->FinishOptimalWrite();

    // cleanup
    fclose(m_pFile);
    m_pFile = NULL;
    fclose(pReadFile);

    // move temporary file into place
    Rename(m_fileName, fileName);
}
Пример #26
0
void MP4File::CreateIsmaODUpdateCommandFromFileForStream(
    MP4TrackId audioTrackId,
    MP4TrackId videoTrackId,
    u_int8_t** ppBytes,
    u_int64_t* pNumBytes)
{
    MP4DescriptorProperty* pAudioEsd = NULL;
    MP4Integer8Property* pAudioSLConfigPredef = NULL;
    MP4BitfieldProperty* pAudioAccessUnitEndFlag = NULL;
    int oldAudioUnitEndFlagValue = 0;
    MP4DescriptorProperty* pVideoEsd = NULL;
    MP4Integer8Property* pVideoSLConfigPredef = NULL;
    MP4BitfieldProperty* pVideoAccessUnitEndFlag = NULL;
    int oldVideoUnitEndFlagValue = 0;
    MP4IntegerProperty* pAudioEsdId = NULL;
    MP4IntegerProperty* pVideoEsdId = NULL;

    if (audioTrackId != MP4_INVALID_TRACK_ID) {
        // changed mp4a to * to handle enca case
        MP4Atom* pEsdsAtom =
            FindAtom(MakeTrackName(audioTrackId,
                                   "mdia.minf.stbl.stsd.*.esds"));
        ASSERT(pEsdsAtom);

        pAudioEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
        // ESID is 0 for file, stream needs to be non-ze
        pAudioEsd->FindProperty("ESID",
                                (MP4Property**)&pAudioEsdId);

        ASSERT(pAudioEsdId);
        pAudioEsdId->SetValue(audioTrackId);

        // SL config needs to change from 2 (file) to 1 (null)
        pAudioEsd->FindProperty("slConfigDescr.predefined",
                                (MP4Property**)&pAudioSLConfigPredef);
        ASSERT(pAudioSLConfigPredef);
        pAudioSLConfigPredef->SetValue(0);

        pAudioEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
                                (MP4Property **)&pAudioAccessUnitEndFlag);
        oldAudioUnitEndFlagValue =
            pAudioAccessUnitEndFlag->GetValue();
        pAudioAccessUnitEndFlag->SetValue(1);
    }

    if (videoTrackId != MP4_INVALID_TRACK_ID) {
        // changed mp4v to * to handle encv case
        MP4Atom* pEsdsAtom =
            FindAtom(MakeTrackName(videoTrackId,
                                   "mdia.minf.stbl.stsd.*.esds"));
        ASSERT(pEsdsAtom);

        pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
        pVideoEsd->FindProperty("ESID",
                                (MP4Property**)&pVideoEsdId);

        ASSERT(pVideoEsdId);
        pVideoEsdId->SetValue(videoTrackId);

        // SL config needs to change from 2 (file) to 1 (null)
        pVideoEsd->FindProperty("slConfigDescr.predefined",
                                (MP4Property**)&pVideoSLConfigPredef);
        ASSERT(pVideoSLConfigPredef);
        pVideoSLConfigPredef->SetValue(0);

        pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
                                (MP4Property **)&pVideoAccessUnitEndFlag);
        oldVideoUnitEndFlagValue =
            pVideoAccessUnitEndFlag->GetValue();
        pVideoAccessUnitEndFlag->SetValue(1);
    }

    CreateIsmaODUpdateCommandForStream(
        pAudioEsd, pVideoEsd, ppBytes, pNumBytes);
    VERBOSE_ISMA(GetVerbosity(),
                 printf("After CreateImsaODUpdateCommandForStream len %llu =\n", *pNumBytes); MP4HexDump(*ppBytes, *pNumBytes));
    // return SL config values to 2 (file)
    // return ESID values to 0
    if (pAudioSLConfigPredef) {
        pAudioSLConfigPredef->SetValue(2);
    }
    if (pAudioEsdId) {
        pAudioEsdId->SetValue(0);
    }
    if (pAudioAccessUnitEndFlag) {
        pAudioAccessUnitEndFlag->SetValue(oldAudioUnitEndFlagValue );
    }
    if (pVideoEsdId) {
        pVideoEsdId->SetValue(0);
    }
    if (pVideoSLConfigPredef) {
        pVideoSLConfigPredef->SetValue(2);
    }
    if (pVideoAccessUnitEndFlag) {
        pVideoAccessUnitEndFlag->SetValue(oldVideoUnitEndFlagValue );
    }
}