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

📄 mp4track.cpp

📁 6410BSP1
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved. *  * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, * and was contributed by Ximpo Group Ltd. * * Portions created by Ximpo Group Ltd. are * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved. *  * Contributor(s):  *        Dave Mackie            dmackie@cisco.com *        Alix Marchandise-Franquet    alix@cisco.com *              Ximpo Group Ltd.                mp4v2@ximpo.com */#include "mp4common.h"#define AMR_UNINITIALIZED -1#define AMR_TRUE 0#define AMR_FALSE 1MP4Track::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_bytesPerSample should be set to 1, except for the    // quicktime audio constant bit rate samples, which have non-1 values    m_bytesPerSample = 1;    m_samplesPerChunk = 0;    m_durationPerChunk = 0;    m_isAmr = AMR_UNINITIALIZED;    m_curMode = 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");    }    CalculateBytesPerSample();}MP4Track::~MP4Track(){    MP4Free(m_pCachedReadSample);    MP4Free(m_pChunkBuffer);}const char* MP4Track::GetType(){    return m_pTypeProperty->GetValue();}void MP4Track::SetType(const char* type) {    m_pTypeProperty->SetValue(MP4NormalizeTrackType(type,                            m_pFile->GetVerbosity()));}void MP4Track::ReadSample(    MP4SampleId sampleId,    u_int8_t** ppBytes,     u_int32_t* pNumBytes,     MP4Timestamp* pStartTime,     MP4Duration* pDuration,    MP4Duration* pRenderingOffset,     bool* pIsSyncSample){    if (sampleId == MP4_INVALID_SAMPLE_ID) {        throw new MP4Error("sample id can't be zero",             "MP4Track::ReadSample");    }    // handle unusual case of wanting to read a sample    // that is still sitting in the write chunk buffer    if (m_pChunkBuffer && sampleId >= m_writeSampleId - m_chunkSamples) {        WriteChunkBuffer();    }    FILE* pFile = GetSampleFile(sampleId);    if (pFile == (FILE*)-1) {        throw new MP4Error("sample is located in an inaccessible file",            "MP4Track::ReadSample");    }    u_int64_t fileOffset = GetSampleFileOffset(sampleId);    u_int32_t sampleSize = GetSampleSize(sampleId);    if (*ppBytes != NULL && *pNumBytes < sampleSize) {        throw new MP4Error("sample buffer is too small",             "MP4Track::ReadSample");    }    *pNumBytes = sampleSize;    VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),        printf("ReadSample: track %u id %u offset 0x"X64" size %u (0x%x)\n",            m_trackId, sampleId, fileOffset, *pNumBytes, *pNumBytes));    bool bufferMalloc = false;    if (*ppBytes == NULL) {        *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);        bufferMalloc = true;    }    u_int64_t oldPos = m_pFile->GetPosition(pFile); // only used in mode == 'w'    __try {         m_pFile->SetPosition(fileOffset, pFile);        m_pFile->ReadBytes(*ppBytes, *pNumBytes, pFile);        if (pStartTime || pDuration) {            GetSampleTimes(sampleId, pStartTime, pDuration);            VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),                printf("ReadSample:  start "U64" duration "D64"\n",                    (pStartTime ? *pStartTime : 0),                     (pDuration ? *pDuration : 0)));        }        if (pRenderingOffset) {            *pRenderingOffset = GetSampleRenderingOffset(sampleId);            VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),                printf("ReadSample:  renderingOffset "D64"\n",                    *pRenderingOffset));        }        if (pIsSyncSample) {            *pIsSyncSample = IsSyncSample(sampleId);            VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),                printf("ReadSample:  isSyncSample %u\n",                    *pIsSyncSample));        }    }    __except (EXCEPTION_EXECUTE_HANDLER) {        if (bufferMalloc) {            // let's not leak memory            MP4Free(*ppBytes);            *ppBytes = NULL;        }        if (m_pFile->GetMode() == 'w') {            m_pFile->SetPosition(oldPos, pFile);        }//        throw e;    }    if (m_pFile->GetMode() == 'w') {        m_pFile->SetPosition(oldPos, pFile);    }}void MP4Track::ReadSampleFragment(    MP4SampleId sampleId,    u_int32_t sampleOffset,    u_int16_t sampleLength,    u_int8_t* pDest){    if (sampleId == MP4_INVALID_SAMPLE_ID) {        throw new MP4Error("invalid sample id",             "MP4Track::ReadSampleFragment");    }    if (sampleId != m_cachedReadSampleId) {        MP4Free(m_pCachedReadSample);        m_pCachedReadSample = NULL;        m_cachedReadSampleSize = 0;        m_cachedReadSampleId = MP4_INVALID_SAMPLE_ID;        ReadSample(            sampleId,            &m_pCachedReadSample,            &m_cachedReadSampleSize);        m_cachedReadSampleId = sampleId;    }    if (sampleOffset + sampleLength > m_cachedReadSampleSize) {        throw new MP4Error("offset and/or length are too large",             "MP4Track::ReadSampleFragment");    }    memcpy(pDest, &m_pCachedReadSample[sampleOffset], sampleLength);}void MP4Track::WriteSample(    const u_int8_t* pBytes,     u_int32_t numBytes,    MP4Duration duration,     MP4Duration renderingOffset,     bool isSyncSample){    u_int8_t curMode = 0;    VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(),        printf("WriteSample: track %u id %u size %u (0x%x) ",            m_trackId, m_writeSampleId, numBytes, numBytes));    if (pBytes == NULL && numBytes > 0) {        throw new MP4Error("no sample data", "MP4WriteSample");    }    if (m_isAmr == AMR_UNINITIALIZED ) {        // figure out if this is an AMR audio track        if (m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.samr") ||            m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.sawb")) {            m_isAmr = AMR_TRUE;            m_curMode = (pBytes[0] >> 3) & 0x000F;        } else {            m_isAmr = AMR_FALSE;        }    }        if (m_isAmr == AMR_TRUE) {        curMode = (pBytes[0] >> 3) &0x000F; // The mode is in the first byte    }    if (duration == MP4_INVALID_DURATION) {        duration = GetFixedSampleDuration();    }    VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(),        printf("duration "U64"\n", duration));    if ((m_isAmr == AMR_TRUE) &&        (m_curMode != curMode)) {        WriteChunkBuffer();        m_curMode = curMode;    }    // append sample bytes to chunk buffer    m_pChunkBuffer = (u_int8_t*)MP4Realloc(m_pChunkBuffer,         m_chunkBufferSize + numBytes);    memcpy(&m_pChunkBuffer[m_chunkBufferSize], pBytes, numBytes);    m_chunkBufferSize += numBytes;    m_chunkSamples++;    m_chunkDuration += duration;    UpdateSampleSizes(m_writeSampleId, numBytes);    UpdateSampleTimes(duration);    UpdateRenderingOffsets(m_writeSampleId, renderingOffset);    UpdateSyncSamples(m_writeSampleId, isSyncSample);    if (IsChunkFull(m_writeSampleId)) {        WriteChunkBuffer();        m_curMode = curMode;    }    UpdateDurations(duration);    UpdateModificationTimes();    m_writeSampleId++;}

⌨️ 快捷键说明

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