⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4track.cpp

📁 6410BSP1
💻 CPP
📖 第 1 页 / 共 4 页
字号:
void MP4Track::WriteChunkBuffer(){    if (m_chunkBufferSize == 0) {        return;    }    u_int64_t chunkOffset = m_pFile->GetPosition();    // write chunk buffer    m_pFile->WriteBytes(m_pChunkBuffer, m_chunkBufferSize);    VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(),        printf("WriteChunk: track %u offset 0x"X64" size %u (0x%x) numSamples %u\n",            m_trackId, chunkOffset, m_chunkBufferSize,             m_chunkBufferSize, m_chunkSamples));    UpdateSampleToChunk(m_writeSampleId,         m_pChunkCountProperty->GetValue() + 1,         m_chunkSamples);    UpdateChunkOffsets(chunkOffset);    // clean up chunk buffer    MP4Free(m_pChunkBuffer);    m_pChunkBuffer = NULL;    m_chunkBufferSize = 0;    m_chunkSamples = 0;    m_chunkDuration = 0;}void MP4Track::FinishWrite(){    // write out any remaining samples in chunk buffer    WriteChunkBuffer();    // record buffer size and bitrates    MP4BitfieldProperty* pBufferSizeProperty;    if (m_pTrakAtom->FindProperty(      "trak.mdia.minf.stbl.stsd.*.esds.decConfigDescr.bufferSizeDB",      (MP4Property**)&pBufferSizeProperty)) {        pBufferSizeProperty->SetValue(GetMaxSampleSize());    }    MP4Integer32Property* pBitrateProperty;    if (m_pTrakAtom->FindProperty(      "trak.mdia.minf.stbl.stsd.*.esds.decConfigDescr.maxBitrate",      (MP4Property**)&pBitrateProperty)) {        pBitrateProperty->SetValue(GetMaxBitrate());    }    if (m_pTrakAtom->FindProperty(      "trak.mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate",      (MP4Property**)&pBitrateProperty)) {        pBitrateProperty->SetValue(GetAvgBitrate());    }}bool MP4Track::IsChunkFull(MP4SampleId sampleId){    if (m_samplesPerChunk) {        return m_chunkSamples >= m_samplesPerChunk;    }    ASSERT(m_durationPerChunk);    return m_chunkDuration >= m_durationPerChunk;}u_int32_t MP4Track::GetNumberOfSamples(){    return m_pStszSampleCountProperty->GetValue();}u_int32_t MP4Track::GetSampleSize(MP4SampleId sampleId){    u_int32_t fixedSampleSize =         m_pStszFixedSampleSizeProperty->GetValue();     if (fixedSampleSize != 0) {      return fixedSampleSize * m_bytesPerSample;    }    return m_bytesPerSample *       m_pStszSampleSizeProperty->GetValue(sampleId - 1);}u_int32_t MP4Track::GetMaxSampleSize(){    u_int32_t fixedSampleSize =         m_pStszFixedSampleSizeProperty->GetValue();     if (fixedSampleSize != 0) {        return fixedSampleSize * m_bytesPerSample;    }    u_int32_t maxSampleSize = 0;    u_int32_t numSamples = m_pStszSampleSizeProperty->GetCount();    for (MP4SampleId sid = 1; sid <= numSamples; sid++) {        u_int32_t sampleSize =            m_pStszSampleSizeProperty->GetValue(sid - 1);        if (sampleSize > maxSampleSize) {            maxSampleSize = sampleSize;        }    }    return maxSampleSize * m_bytesPerSample;}u_int64_t MP4Track::GetTotalOfSampleSizes(){  uint64_t retval;    u_int32_t fixedSampleSize =         m_pStszFixedSampleSizeProperty->GetValue();     // if fixed sample size, just need to multiply by number of samples    if (fixedSampleSize != 0) {      retval = m_bytesPerSample;      retval *= fixedSampleSize;      retval *= GetNumberOfSamples();      return retval;    }    // else non-fixed sample size, sum them    u_int64_t totalSampleSizes = 0;    u_int32_t numSamples = m_pStszSampleSizeProperty->GetCount();    for (MP4SampleId sid = 1; sid <= numSamples; sid++) {        u_int32_t sampleSize =            m_pStszSampleSizeProperty->GetValue(sid - 1);        totalSampleSizes += sampleSize;    }    return totalSampleSizes * m_bytesPerSample;}void MP4Track::UpdateSampleSizes(MP4SampleId sampleId, u_int32_t numBytes){  if (m_bytesPerSample > 1) {    if ((numBytes % m_bytesPerSample) != 0) {      // error      VERBOSE_ERROR(m_pFile->GetVerbosity(),             printf("UpdateSampleSize: numBytes %u not divisible by bytesPerSample %u sampleId %u\n",                numBytes, m_bytesPerSample, sampleId);            );    }    numBytes /= m_bytesPerSample;  }    // for first sample    if (sampleId == 1) {        if (numBytes > 0) {            // presume sample size is fixed            m_pStszFixedSampleSizeProperty->SetValue(numBytes);         } else {            // special case of first sample is zero bytes in length            // leave m_pStszFixedSampleSizeProperty at 0            // start recording variable sample sizes                m_pStszFixedSampleSizeProperty->SetValue(0);             m_pStszSampleSizeProperty->AddValue(0);        }    } else { // sampleId > 1        u_int32_t fixedSampleSize =             m_pStszFixedSampleSizeProperty->GetValue();         if (fixedSampleSize == 0 || numBytes != fixedSampleSize) {            // sample size is not fixed            if (fixedSampleSize) {                // need to clear fixed sample size                m_pStszFixedSampleSizeProperty->SetValue(0);                 // and create sizes for all previous samples                for (MP4SampleId sid = 1; sid < sampleId; sid++) {                    m_pStszSampleSizeProperty->AddValue(fixedSampleSize);                }            }            // add size value for this sample            m_pStszSampleSizeProperty->AddValue(numBytes);        }    }    m_pStszSampleCountProperty->IncrementValue();#if 0    printf("track %u sample id %u bytes %u fixed %u count %u prop %u\n",            m_trackId, sampleId, numBytes,           m_pStszFixedSampleSizeProperty->GetValue(),           m_pStszSampleSizeProperty->GetCount(),           m_pStszSampleCountProperty->GetValue());#endif}u_int32_t MP4Track::GetAvgBitrate(){    if (GetDuration() == 0) {        return 0;    }    double calc = UINT64_TO_DOUBLE(GetTotalOfSampleSizes());    // this is a bit better - we use the whole duration    calc *= 8.0;    calc *= GetTimeScale();    calc /=    UINT64_TO_DOUBLE(GetDuration());    // we might want to think about rounding to the next 100 or 1000    return (uint32_t) ceil(calc);}u_int32_t MP4Track::GetMaxBitrate(){    u_int32_t timeScale = GetTimeScale();    MP4SampleId numSamples = GetNumberOfSamples();    u_int32_t maxBytesPerSec = 0;    u_int32_t bytesThisSec = 0;    MP4Timestamp thisSecStart = 0;    MP4Timestamp lastSampleTime = 0;    uint32_t lastSampleSize = 0;    MP4SampleId thisSecStartSid = 1;    for (MP4SampleId sid = 1; sid <= numSamples; sid++) {      uint32_t sampleSize;      MP4Timestamp sampleTime;      sampleSize = GetSampleSize(sid);      GetSampleTimes(sid, &sampleTime, NULL);            if (sampleTime < thisSecStart + timeScale) {        bytesThisSec += sampleSize;        lastSampleSize = sampleSize;        lastSampleTime = sampleTime;      } else {        // we've already written the last sample and sampleSize.        // this means that we've probably overflowed the last second        // calculate the time we've overflowed        MP4Duration overflow_dur =           (thisSecStart + timeScale) - lastSampleTime;        // calculate the duration of the last sample        MP4Duration lastSampleDur = sampleTime - lastSampleTime;        uint32_t overflow_bytes;        // now, calculate the number of bytes we overflowed.  Round up.        overflow_bytes =           ((lastSampleSize * overflow_dur) + (lastSampleDur - 1)) / lastSampleDur;        if (bytesThisSec - overflow_bytes > maxBytesPerSec) {          maxBytesPerSec = bytesThisSec - overflow_bytes;        }        // now adjust the values for this sample.  Remove the bytes        // from the first sample in this time frame        lastSampleTime = sampleTime;        lastSampleSize = sampleSize;        bytesThisSec += sampleSize;        bytesThisSec -= GetSampleSize(thisSecStartSid);        thisSecStartSid++;        GetSampleTimes(thisSecStartSid, &thisSecStart, NULL);      }    }    return maxBytesPerSec * 8;}u_int32_t MP4Track::GetSampleStscIndex(MP4SampleId sampleId){    u_int32_t stscIndex;    u_int32_t numStscs = m_pStscCountProperty->GetValue();    if (numStscs == 0) {        throw new MP4Error("No data chunks exist", "GetSampleStscIndex");    }    for (stscIndex = 0; stscIndex < numStscs; stscIndex++) {        if (sampleId < m_pStscFirstSampleProperty->GetValue(stscIndex)) {            ASSERT(stscIndex != 0);            stscIndex -= 1;            break;        }    }    if (stscIndex == numStscs) {        ASSERT(stscIndex != 0);        stscIndex -= 1;    }    return stscIndex;}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 {        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;                }            }        }     }    if (m_lastSampleFile) {        fclose(m_lastSampleFile);    }    // cache the answer    m_lastStsdIndex = stsdIndex;    m_lastSampleFile = pFile;    return pFile;}u_int64_t MP4Track::GetSampleFileOffset(MP4SampleId sampleId){    u_int32_t stscIndex =        GetSampleStscIndex(sampleId);    // firstChunk is the chunk index of the first chunk with     // samplesPerChunk samples in the chunk.  There may be multiples -    // ie: several chunks with the same number of samples per chunk.    u_int32_t firstChunk =         m_pStscFirstChunkProperty->GetValue(stscIndex);    MP4SampleId firstSample =         m_pStscFirstSampleProperty->GetValue(stscIndex);    u_int32_t samplesPerChunk =         m_pStscSamplesPerChunkProperty->GetValue(stscIndex);    // chunkId tells which is the absolute chunk number that this sample    // is stored in.    MP4ChunkId chunkId = firstChunk +        ((sampleId - firstSample) / samplesPerChunk);    // chunkOffset is the file offset (absolute) for the start of the chunk    u_int64_t chunkOffset = m_pChunkOffsetProperty->GetValue(chunkId - 1);    MP4SampleId firstSampleInChunk =         sampleId - ((sampleId - firstSample) % samplesPerChunk);    // need cumulative samples sizes from firstSample to sampleId - 1    u_int32_t sampleOffset = 0;    for (MP4SampleId i = firstSampleInChunk; i < sampleId; i++) {        sampleOffset += GetSampleSize(i);    }    return chunkOffset + sampleOffset;}void MP4Track::UpdateSampleToChunk(MP4SampleId sampleId,     MP4ChunkId chunkId, u_int32_t samplesPerChunk){    u_int32_t numStsc = m_pStscCountProperty->GetValue();    // if samplesPerChunk == samplesPerChunk of last entry    if (numStsc && samplesPerChunk ==       m_pStscSamplesPerChunkProperty->GetValue(numStsc-1)) {        // nothing to do    } else {        // add stsc entry        m_pStscFirstChunkProperty->AddValue(chunkId);        m_pStscSamplesPerChunkProperty->AddValue(samplesPerChunk);        m_pStscSampleDescrIndexProperty->AddValue(1);        m_pStscFirstSampleProperty->AddValue(sampleId - samplesPerChunk + 1);        m_pStscCountProperty->IncrementValue();    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -