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

📄 mp4file.cpp

📁 6410BSP1
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * 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 - 2005.  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 *              Bill May                  wmay@cisco.com */#include "mp4common.h"#ifdef SIMON_CHANGEDstatic void char2wchar_t(const char *str_char, wchar_t *str_wchar){    int        i, j;    int        leng;    char       c;    leng = strlen(str_char);    for (i=j=0; i<leng; i++, j++)    {        c = str_char[i];        if (c == 0) {            str_wchar[j] = '\0';            break;        }        else if (c > 0) {            str_wchar[j] = (wchar_t)str_char[i];        }        else {            // Currently the non-alphanumeric characters are not supported.            i++;        }    }    str_wchar[j] = 0;}static void wchar_t2char(const wchar_t *str_wchar, char *str_char){    int        i, j;    int        leng;    wchar_t    c;    leng = wcslen(str_wchar);    for (i=j=0; i<leng; i++, j++)    {        c = str_wchar[i];        if (c == 0) {            str_char[j] = '\0';            break;        }        else if (c < 0x80) {            str_char[j] = (char)str_wchar[i];        }        else {            // Currently the non-alphanumeric characters are not supported.            i++;        }    }    str_char[j] = '\0';}#endifMP4File::MP4File(u_int32_t verbosity){    m_fileName = NULL;    #ifdef _WIN32    m_fileName_w = NULL;    #endif    m_pFile = NULL;    m_orgFileSize = 0;    m_fileSize = 0;    m_pRootAtom = NULL;    m_odTrackId = MP4_INVALID_TRACK_ID;    m_verbosity = verbosity;// = MP4_DETAILS_READ;    m_mode = 0;    m_createFlags = 0;    m_useIsma = false;    m_pModificationProperty = NULL;    m_pTimeScaleProperty = NULL;    m_pDurationProperty = NULL;    m_memoryBuffer = NULL;    m_memoryBufferSize = 0;    m_memoryBufferPosition = 0;    m_numReadBits = 0;    m_bufReadBits = 0;    m_numWriteBits = 0;    m_bufWriteBits = 0;    m_editName = NULL;}MP4File::~MP4File(){    MP4Free(m_fileName);    #ifdef _WIN32    MP4Free(m_fileName_w);    #endif    if (m_pFile != NULL) {      // not closed ?      fclose(m_pFile);      m_pFile = NULL;    }    delete m_pRootAtom;    for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {        delete m_pTracks[i];    }    MP4Free(m_memoryBuffer);    // just in case    CHECK_AND_FREE(m_editName);    }void MP4File::Read(const char* fileName){    m_fileName = MP4Stralloc(fileName);    m_mode = 'r';    Open("rb");    ReadFromFile();    CacheProperties();}#ifdef _WIN32void MP4File::Read(const wchar_t* fileName){    m_fileName_w = MP4Stralloc(fileName);    m_mode = 'r';    Open(L"rb");    ReadFromFile();    CacheProperties();}#endifvoid MP4File::Create(const char* fileName, u_int32_t flags,              int add_ftyp, int add_iods,              char* majorBrand, u_int32_t minorVersion,              char** supportedBrands, u_int32_t supportedBrandsCount){    m_fileName = MP4Stralloc(fileName);    m_mode = 'w';    m_createFlags = flags;    Open("wb+");    // generate a skeletal atom tree    m_pRootAtom = MP4Atom::CreateAtom(NULL);    m_pRootAtom->SetFile(this);    m_pRootAtom->Generate();    if (add_ftyp != 0) {      MakeFtypAtom(majorBrand, minorVersion,                supportedBrands, supportedBrandsCount);    }    CacheProperties();    // create mdat, and insert it after ftyp, and before moov    InsertChildAtom(m_pRootAtom, "mdat",             add_ftyp != 0 ? 1 : 0);    // start writing    m_pRootAtom->BeginWrite();    if (add_iods != 0) {      AddChildAtom("moov", "iods");    }}bool MP4File::Use64Bits (const char *atomName){  uint32_t atomid = ATOMID(atomName);  if (atomid == ATOMID("mdat") || atomid == ATOMID("stbl")) {    return (m_createFlags & MP4_CREATE_64BIT_DATA) == MP4_CREATE_64BIT_DATA;  }   if (atomid == ATOMID("mvhd") ||      atomid == ATOMID("tkhd") ||      atomid == ATOMID("mdhd")) {    return (m_createFlags & MP4_CREATE_64BIT_TIME) == MP4_CREATE_64BIT_TIME;  }  return false;}void MP4File::Check64BitStatus (const char *atomName){  uint32_t atomid = ATOMID(atomName);  if (atomid == ATOMID("mdat") || atomid == ATOMID("stbl")) {    m_createFlags |= MP4_CREATE_64BIT_DATA;  } else if (atomid == ATOMID("mvhd") ||         atomid == ATOMID("tkhd") ||         atomid == ATOMID("mdhd")) {    m_createFlags |= MP4_CREATE_64BIT_TIME;  }}    void MP4File::Modify(const char* fileName){    m_fileName = MP4Stralloc(fileName);    m_mode = 'r';    Open("rb+");    ReadFromFile();    m_mode = 'w';    // find the moov atom    MP4Atom* pMoovAtom = m_pRootAtom->FindAtom("moov");    u_int32_t numAtoms;    if (pMoovAtom == NULL) {        // there isn't one, odd but we can still proceed        pMoovAtom = AddChildAtom(m_pRootAtom, "moov");    } else {        numAtoms = m_pRootAtom->GetNumberOfChildAtoms();        // work backwards thru the top level atoms        int32_t i;        bool lastAtomIsMoov = true;        MP4Atom* pLastAtom = NULL;        for (i = numAtoms - 1; i >= 0; i--) {            MP4Atom* pAtom = m_pRootAtom->GetChildAtom(i);            const char* type = pAtom->GetType();                        // get rid of any trailing free or skips            if (!strcmp(type, "free") || !strcmp(type, "skip")) {                m_pRootAtom->DeleteChildAtom(pAtom);                continue;            }            if (strcmp(type, "moov")) {                if (pLastAtom == NULL) {                    pLastAtom = pAtom;                    lastAtomIsMoov = false;                }                continue;            }            // now at moov atom            // multiple moov atoms?!?            if (pAtom != pMoovAtom) {#ifdef SIMON_CHANGED                printf("\n[%s]  %s", "MP4Modify", "Badly formed mp4 file, multiple moov atoms");                RaiseException(1, 0, 0, NULL);#else//                throw new MP4Error(//                    "Badly formed mp4 file, multiple moov atoms", //                    "MP4Modify");#endif            }            if (lastAtomIsMoov) {                // position to start of moov atom,                // effectively truncating file                 // prior to adding new mdat                SetPosition(pMoovAtom->GetStart());            } else { // last atom isn't moov                // need to place a free atom                 MP4Atom* pFreeAtom = MP4Atom::CreateAtom("free");                // in existing position of the moov atom                m_pRootAtom->InsertChildAtom(pFreeAtom, i);                m_pRootAtom->DeleteChildAtom(pMoovAtom);                m_pRootAtom->AddChildAtom(pMoovAtom);                // write free atom to disk                SetPosition(pMoovAtom->GetStart());                pFreeAtom->SetSize(pMoovAtom->GetSize());                pFreeAtom->Write();                // finally set our file position to the end of the last atom                SetPosition(pLastAtom->GetEnd());            }            break;        }        ASSERT(i != -1);    }    CacheProperties();    // of moov atom    numAtoms = m_pRootAtom->GetNumberOfChildAtoms();    // insert another mdat prior to moov atom (the last atom)    MP4Atom* pMdatAtom = InsertChildAtom(m_pRootAtom, "mdat", numAtoms - 1);    // start writing new mdat    pMdatAtom->BeginWrite();}void MP4File::Optimize(const char* orgFileName, const char* newFileName){    m_fileName = MP4Stralloc(orgFileName);    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);    #ifdef _WIN32    MP4Free(m_fileName_w);    #endif    // create a temporary file if necessary    if (newFileName == NULL) {        m_fileName = MP4Stralloc(TempFileName());    } else {        m_fileName = MP4Stralloc(newFileName);    }    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    if (newFileName == NULL) {        Rename(m_fileName, orgFileName);    }}void MP4File::RewriteMdat(FILE* pReadFile, FILE* pWriteFile){    u_int32_t numTracks = m_pTracks.Size();    MP4ChunkId* chunkIds = new MP4ChunkId[numTracks];    MP4ChunkId* maxChunkIds = new MP4ChunkId[numTracks];    MP4Timestamp* nextChunkTimes = new MP4Timestamp[numTracks];    for (u_int32_t i = 0; i < numTracks; i++) {        chunkIds[i] = 1;        maxChunkIds[i] = m_pTracks[i]->GetNumberOfChunks();        nextChunkTimes[i] = MP4_INVALID_TIMESTAMP;    }    while (true) {        u_int32_t nextTrackIndex = (u_int32_t)-1;        MP4Timestamp nextTime = MP4_INVALID_TIMESTAMP;        for (u_int32_t i = 0; i < numTracks; i++) {            if (chunkIds[i] > maxChunkIds[i]) {                continue;            }            if (nextChunkTimes[i] == MP4_INVALID_TIMESTAMP) {                MP4Timestamp chunkTime =                    m_pTracks[i]->GetChunkTime(chunkIds[i]);                nextChunkTimes[i] = MP4ConvertTime(chunkTime,                    m_pTracks[i]->GetTimeScale(), GetTimeScale());            }            // time is not earliest so far            if (nextChunkTimes[i] > nextTime) {                continue;            }            // prefer hint tracks to media tracks if times are equal            if (nextChunkTimes[i] == nextTime               && strcmp(m_pTracks[i]->GetType(), MP4_HINT_TRACK_TYPE)) {                continue;            }            // this is our current choice of tracks            nextTime = nextChunkTimes[i];            nextTrackIndex = i;        }        if (nextTrackIndex == (u_int32_t)-1) {            break;        }        // point into original mp4 file for read chunk call        m_pFile = pReadFile;        m_mode = 'r';        u_int8_t* pChunk;        u_int32_t chunkSize;        m_pTracks[nextTrackIndex]->            ReadChunk(chunkIds[nextTrackIndex], &pChunk, &chunkSize);        // point back at the new mp4 file for write chunk        m_pFile = pWriteFile;        m_mode = 'w';        m_pTracks[nextTrackIndex]->            RewriteChunk(chunkIds[nextTrackIndex], pChunk, chunkSize);        MP4Free(pChunk);        chunkIds[nextTrackIndex]++;        nextChunkTimes[nextTrackIndex] = MP4_INVALID_TIMESTAMP;    }    delete [] chunkIds;    delete [] maxChunkIds;    delete [] nextChunkTimes;}void MP4File::Open(const char* fmode){    ASSERT(m_pFile == NULL);

⌨️ 快捷键说明

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