void MP4StsdAtom::Read() { /* do the usual read */ MP4Atom::Read(); // check that number of children == entryCount MP4Integer32Property* pCount = (MP4Integer32Property*)m_pProperties[2]; if (m_pChildAtoms.Size() != pCount->GetValue()) { VERBOSE_READ(GetVerbosity(), printf("Warning: stsd inconsistency with number of entries")); /* fix it */ pCount->SetReadOnly(false); pCount->SetValue(m_pChildAtoms.Size()); pCount->SetReadOnly(true); } }
MP4StsdAtom::MP4StsdAtom() : MP4Atom("stsd") { AddVersionAndFlags(); MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); pCount->SetReadOnly(); AddProperty(pCount); ExpectChildAtom("mp4a", Optional, Many); ExpectChildAtom("enca", Optional, Many); ExpectChildAtom("mp4s", Optional, Many); ExpectChildAtom("mp4v", Optional, Many); ExpectChildAtom("encv", Optional, Many); ExpectChildAtom("rtp ", Optional, Many); ExpectChildAtom("samr", Optional, Many); // For AMR-NB ExpectChildAtom("sawb", Optional, Many); // For AMR-WB ExpectChildAtom("s263", Optional, Many); // For H.263 ExpectChildAtom("avc1", Optional, Many); ExpectChildAtom("alac", Optional, Many); }
MP4FtypAtom::MP4FtypAtom() : MP4Atom("ftyp") { MP4StringProperty* pProp = new MP4StringProperty("majorBrand"); pProp->SetFixedLength(4); AddProperty(pProp); /* 0 */ AddProperty( /* 1 */ new MP4Integer32Property("minorVersion")); MP4Integer32Property* pCount = new MP4Integer32Property("compatibleBrandsCount"); pCount->SetImplicit(); AddProperty(pCount); /* 2 */ MP4TableProperty* pTable = new MP4TableProperty("compatibleBrands", pCount); AddProperty(pTable); /* 3 */ pProp = new MP4StringProperty("brand"); pProp->SetFixedLength(4); pTable->AddProperty(pProp); }
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); } }
MP4Track::MP4Track(MP4File* pFile, MP4Atom* pTrakAtom) { m_pFile = pFile; m_pTrakAtom = pTrakAtom; m_lastStsdIndex = 0; m_lastSampleFile = NULL; m_cachedReadSampleId = MP4_INVALID_SAMPLE_ID; m_pCachedReadSample = NULL; m_cachedReadSampleSize = 0; m_writeSampleId = 1; m_fixedSampleDuration = 0; m_pChunkBuffer = NULL; m_chunkBufferSize = 0; m_chunkSamples = 0; m_chunkDuration = 0; m_samplesPerChunk = 0; m_durationPerChunk = 0; bool success = true; MP4Integer32Property* pTrackIdProperty; success &= m_pTrakAtom->FindProperty( "trak.tkhd.trackId", (MP4Property**)&pTrackIdProperty); if (success) { m_trackId = pTrackIdProperty->GetValue(); } success &= m_pTrakAtom->FindProperty( "trak.mdia.mdhd.timeScale", (MP4Property**)&m_pTimeScaleProperty); if (success) { // default chunking is 1 second of samples m_durationPerChunk = m_pTimeScaleProperty->GetValue(); } success &= m_pTrakAtom->FindProperty( "trak.tkhd.duration", (MP4Property**)&m_pTrackDurationProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.mdhd.duration", (MP4Property**)&m_pMediaDurationProperty); success &= m_pTrakAtom->FindProperty( "trak.tkhd.modificationTime", (MP4Property**)&m_pTrackModificationProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.mdhd.modificationTime", (MP4Property**)&m_pMediaModificationProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.hdlr.handlerType", (MP4Property**)&m_pTypeProperty); // get handles on sample size information success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsz.sampleSize", (MP4Property**)&m_pStszFixedSampleSizeProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsz.sampleCount", (MP4Property**)&m_pStszSampleCountProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsz.entries.sampleSize", (MP4Property**)&m_pStszSampleSizeProperty); // get handles on information needed to map sample id's to file offsets success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsc.entryCount", (MP4Property**)&m_pStscCountProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsc.entries.firstChunk", (MP4Property**)&m_pStscFirstChunkProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsc.entries.samplesPerChunk", (MP4Property**)&m_pStscSamplesPerChunkProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsc.entries.sampleDescriptionIndex", (MP4Property**)&m_pStscSampleDescrIndexProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsc.entries.firstSample", (MP4Property**)&m_pStscFirstSampleProperty); bool haveStco = m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stco.entryCount", (MP4Property**)&m_pChunkCountProperty); if (haveStco) { success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stco.entries.chunkOffset", (MP4Property**)&m_pChunkOffsetProperty); } else { success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.co64.entryCount", (MP4Property**)&m_pChunkCountProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.co64.entries.chunkOffset", (MP4Property**)&m_pChunkOffsetProperty); } // get handles on sample timing info success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stts.entryCount", (MP4Property**)&m_pSttsCountProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stts.entries.sampleCount", (MP4Property**)&m_pSttsSampleCountProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stts.entries.sampleDelta", (MP4Property**)&m_pSttsSampleDeltaProperty); // get handles on rendering offset info if it exists m_pCttsCountProperty = NULL; m_pCttsSampleCountProperty = NULL; m_pCttsSampleOffsetProperty = NULL; bool haveCtts = m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.ctts.entryCount", (MP4Property**)&m_pCttsCountProperty); if (haveCtts) { success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.ctts.entries.sampleCount", (MP4Property**)&m_pCttsSampleCountProperty); success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.ctts.entries.sampleOffset", (MP4Property**)&m_pCttsSampleOffsetProperty); } // get handles on sync sample info if it exists m_pStssCountProperty = NULL; m_pStssSampleProperty = NULL; bool haveStss = m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stss.entryCount", (MP4Property**)&m_pStssCountProperty); if (haveStss) { success &= m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stss.entries.sampleNumber", (MP4Property**)&m_pStssSampleProperty); } // edit list InitEditListProperties(); // was everything found? if (!success) { throw new MP4Error("invalid track", "MP4Track::MP4Track"); } }