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

📄 mp4file.cpp

📁 mpeg4 video codec mpeg4 video codec
💻 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.  All Rights Reserved. * * Contributor(s): *      Dave Mackie       dmackie@cisco.com *              Alix Marchandise-Franquet alix@cisco.com */#include "mp4common.h"MP4File::MP4File(u_int32_t verbosity){    m_fileName = NULL;    m_pFile = NULL;    m_orgFileSize = 0;    m_fileSize = 0;    m_pRootAtom = NULL;    m_odTrackId = MP4_INVALID_TRACK_ID;    m_verbosity = verbosity;    m_mode = 0;    m_use64bits = false;    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;#ifdef USE_FILE_CALLBACKS    // These are the default for when no callbacks are specified    m_userData = (void*)this;    m_MP4fopen = MP4fopen_cb;    m_MP4fclose = MP4fclose_cb;    m_MP4fread = MP4fread_cb;    m_MP4fwrite = MP4fwrite_cb;    m_MP4fgetpos = MP4fgetpos_cb;    m_MP4fsetpos = MP4fsetpos_cb;    m_MP4filesize = MP4filesize_cb;#endif}MP4File::~MP4File(){    MP4Free(m_fileName);    delete m_pRootAtom;    for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {        delete m_pTracks[i];    }    MP4Free(m_memoryBuffer);    // just in case}void MP4File::Read(const char* fileName){    m_fileName = MP4Stralloc(fileName);    m_mode = 'r';    Open("rb");    ReadFromFile();    CacheProperties();}void MP4File::Create(const char* fileName, bool use64bits){    m_fileName = MP4Stralloc(fileName);    m_mode = 'w';    m_use64bits = use64bits;    Open("wb+");    // generate a skeletal atom tree    m_pRootAtom = MP4Atom::CreateAtom(NULL);    m_pRootAtom->SetFile(this);    m_pRootAtom->Generate();    CacheProperties();    // create mdat, and insert it after ftyp, and before moov    InsertChildAtom(m_pRootAtom, "mdat", 1);    // start writing    m_pRootAtom->BeginWrite();}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) {                throw new MP4Error(                    "Badly formed mp4 file, multiple moov atoms",                    "MP4Modify");            }            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){#if 1//ndef USE_FILE_CALLBACKS    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);    // 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);    }#else    throw new MP4Error(errno, "Function not supported when using callbacks", "MP4Optimize");#endif}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);#ifndef USE_FILE_CALLBACKS#ifdef O_LARGEFILE    // UGH! fopen doesn't open a file in 64-bit mode, period.    // So we need to use open() and then fdopen()    int fd;    int flags = O_LARGEFILE;    if (strchr(fmode, '+')) {        flags |= O_CREAT | O_RDWR;        if (fmode[0] == 'w') {            flags |= O_TRUNC;        }    } else {        if (fmode[0] == 'w') {            flags |= O_CREAT | O_TRUNC | O_WRONLY;        } else {            flags |= O_RDONLY;        }    }    fd = open(m_fileName, flags, 0666);    if (fd >= 0) {        m_pFile = fdopen(fd, fmode);    }#else    m_pFile = fopen(m_fileName, fmode);#endif    if (m_pFile == NULL) {        throw new MP4Error(errno, "failed", "MP4Open");    }#else    u_int32_t rc = m_MP4fopen(m_fileName, fmode, m_userData);    if (rc == 0) {        throw new MP4Error(errno, "failed", "MP4Open");    }#endif    if (m_mode == 'r') {#ifndef USE_FILE_CALLBACKS        struct stat s;        if (fstat(fileno(m_pFile), &s) < 0) {            throw new MP4Error(errno, "stat failed", "MP4Open");        }        m_orgFileSize = m_fileSize = s.st_size;#else        int64_t s = m_MP4filesize(m_userData);        if (s < 0) {            throw new MP4Error(errno, "retreiving filesize failed", "MP4Open");        }        m_orgFileSize = m_fileSize = (u_int64_t)s;#endif    } else {        m_orgFileSize = m_fileSize = 0;    }}void MP4File::ReadFromFile(){    // ensure we start at beginning of file    SetPosition(0);    // create a new root atom    ASSERT(m_pRootAtom == NULL);    m_pRootAtom = MP4Atom::CreateAtom(NULL);    u_int64_t fileSize = GetSize();    m_pRootAtom->SetFile(this);    m_pRootAtom->SetStart(0);    m_pRootAtom->SetSize(fileSize);    m_pRootAtom->SetEnd(fileSize);    m_pRootAtom->Read();    // create MP4Track's for any tracks in the file    GenerateTracks();}void MP4File::GenerateTracks(){    u_int32_t trackIndex = 0;    while (true) {        char trackName[32];        snprintf(trackName, sizeof(trackName), "moov.trak[%u]", trackIndex);        // find next trak atom        MP4Atom* pTrakAtom = m_pRootAtom->FindAtom(trackName);        // done, no more trak atoms        if (pTrakAtom == NULL) {            break;        }        // find track id property        MP4Integer32Property* pTrackIdProperty = NULL;        pTrakAtom->FindProperty(            "trak.tkhd.trackId",            (MP4Property**)&pTrackIdProperty);        // find track type property        MP4StringProperty* pTypeProperty = NULL;        pTrakAtom->FindProperty(            "trak.mdia.hdlr.handlerType",            (MP4Property**)&pTypeProperty);        // ensure we have the basics properties        if (pTrackIdProperty && pTypeProperty) {            m_trakIds.Add(pTrackIdProperty->GetValue());            MP4Track* pTrack = NULL;            try {                if (!strcmp(pTypeProperty->GetValue(), MP4_HINT_TRACK_TYPE)) {                    pTrack = new MP4RtpHintTrack(this, pTrakAtom);                } else {                    pTrack = new MP4Track(this, pTrakAtom);                }                m_pTracks.Add(pTrack);            }            catch (MP4Error* e) {                VERBOSE_ERROR(m_verbosity, e->Print());                delete e;            }            // remember when we encounter the OD track            if (pTrack && !strcmp(pTrack->GetType(), MP4_OD_TRACK_TYPE)) {                if (m_odTrackId == MP4_INVALID_TRACK_ID) {                    m_odTrackId = pTrackIdProperty->GetValue();

⌨️ 快捷键说明

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