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(); }
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 } }
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(); } }
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; }
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; }
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); } }
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; }