📄 mp4v.cpp
字号:
/* * 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. 2000, 2001. All Rights Reserved. * * 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 *///#define DEBUG_MP4V 1//#define DEBUG_MP4V_TS 1/* * Notes: * - file formatted with tabstops == 4 spaces */#include <mp4creator.h>typedef struct mpeg4_frame_t { mpeg4_frame_t *next; MP4Timestamp frameTimestamp; int vopType;} mpeg4_frame_t;/* * Load the next syntatic object from the file * into the supplied buffer, which better be large enough! * * Objects are delineated by 4 byte start codes (0x00 0x00 0x01 0x??) * Objects are padded to byte boundaries, and the encoder assures that * the start code pattern is never generated for encoded data */static int LoadNextObject(FILE* inFile, u_int8_t* pBuf, u_int32_t* pBufSize, u_int8_t* pObjCode){ static u_int8_t state = 0; static u_int8_t nextObjCode = 0; *pBufSize = 0; /* initial state, never read from file before */ if (state == 0) { /* * go looking for first sync word * we discard anything before this */ state = 1; while (state < 5) { /* read a byte */ u_char b; if (fread(&b, 1, 1, inFile) == 0) { // EOF or IO error return 0; } switch (state) { case 1: if (b == 0) { state = 2; } break; case 2: if (b == 0) { state = 3; } break; case 3: if (b == 1) { state = 4; } break; case 4: pBuf[0] = 0; pBuf[1] = 0; pBuf[2] = 1; pBuf[3] = b; (*pObjCode) = (u_int)b; *pBufSize = 4; state = 5; break; } } /* we're primed now */ state = 1; } else if (state == 5) { state = 0; return 0; } else { /* * We have next object code from prevous call * insert start code into buffer */ (*pObjCode) = nextObjCode; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 1; pBuf[(*pBufSize)++] = (u_char)(*pObjCode); } /* read bytes, execute state machine */ while (1) { /* read a byte */ u_char b; if (fread(&b, 1, 1, inFile) == 0) { /* handle EOF */ if (feof(inFile)) { switch (state) { case 3: pBuf[(*pBufSize)++] = 0; /* fall thru */ case 2: pBuf[(*pBufSize)++] = 0; break; } state = 5; return 1; } /* else error */ *pBufSize = 0; return 0; } switch (state) { case 1: if (b == 0) { state = 2; } else { pBuf[(*pBufSize)++] = b; } break; case 2: if (b == 0) { state = 3; } else { pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = b; state = 1; } break; case 3: if (b == 1) { state = 4; } else if (b == 0) { pBuf[(*pBufSize)++] = 0; // state remains 3 } else { pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = b; state = 1; } break; case 4: nextObjCode = b; state = 1; return 1; default: ASSERT(false); } }}MP4TrackId Mp4vCreator(MP4FileHandle mp4File, FILE* inFile, bool doEncrypt, bool allowVariableFrameRate){ bool rc; u_int8_t sampleBuffer[256 * 1024 * 2]; u_int8_t* pCurrentSample = sampleBuffer; u_int32_t maxSampleSize = sizeof(sampleBuffer) / 2; u_int32_t prevSampleSize = 0; // the current syntactical object // typically 1:1 with a sample // but not always, i.e. non-VOP's u_int8_t* pObj = pCurrentSample; u_int32_t objSize; u_int8_t objType; // the current sample MP4SampleId sampleId = 1; MP4Timestamp currentSampleTime = 0; // the last reference VOP MP4SampleId refVopId = 1; MP4Timestamp refVopTime = 0; // track configuration info u_int8_t videoProfileLevel = MPEG4_SP_L3; u_int8_t timeBits = 15; u_int16_t timeTicks = 30000; u_int16_t frameDuration = 3000; u_int16_t frameWidth = 320; u_int16_t frameHeight = 240; u_int32_t esConfigSize = 0; int vopType = 0; int prevVopType = 0; bool foundVOSH = false, foundVO = false, foundVOL = false; u_int32_t lastVopTimeIncrement = 0; bool variableFrameRate = false; bool lastFrame = false; bool haveBframes = false; mpeg4_frame_t *head = NULL, *tail = NULL; // start reading objects until we get the first VOP while (LoadNextObject(inFile, pObj, &objSize, &objType)) { // guard against buffer overflow if (pObj + objSize >= pCurrentSample + maxSampleSize) { fprintf(stderr, "%s: buffer overflow, invalid video stream?\n", ProgName); return MP4_INVALID_TRACK_ID; }#ifdef DEBUG_MP4V if (Verbosity & MP4_DETAILS_SAMPLE) { printf("MP4V type %x size %u\n", objType, objSize); }#endif if (objType == MP4AV_MPEG4_VOSH_START) { MP4AV_Mpeg4ParseVosh(pObj, objSize, &videoProfileLevel); foundVOSH = true; } else if (objType == MP4AV_MPEG4_VO_START) { foundVO = true; } else if (objType == MP4AV_MPEG4_VOL_START) { MP4AV_Mpeg4ParseVol(pObj, objSize, &timeBits, &timeTicks, &frameDuration, &frameWidth, &frameHeight); foundVOL = true;#ifdef DEBUG_MP4V printf("ParseVol: timeBits %u timeTicks %u frameDuration %u\n", timeBits, timeTicks, frameDuration);#endif } else if (foundVOL == true || objType == MP4AV_MPEG4_VOP_START) { esConfigSize = pObj - pCurrentSample; // ready to set up mp4 track break; } /* XXX why do we need this if ? * It looks like it will remove this object ... XXX */ // It does. On Purpose. wmay 6/2004 if (objType != MP4AV_MPEG4_USER_DATA_START) { pObj += objSize; } } if (foundVOSH == false) { fprintf(stderr, "%s: no VOSH header found in MPEG-4 video.\n" "This can cause problems with players other than mp4player. \n", ProgName); } else { if (VideoProfileLevelSpecified && videoProfileLevel != VideoProfileLevel) { fprintf(stderr, "%s: You have specified a different video profile level than was detected in the VOSH header\n" "The level you specified was %d and %d was read from the VOSH\n", ProgName, VideoProfileLevel, videoProfileLevel); } } if (foundVO == false) { fprintf(stderr, "%s: No VO header found in mpeg-4 video.\n" "This can cause problems with players other than mp4player\n", ProgName); } if (foundVOL == false) { fprintf(stderr, "%s: fatal: No VOL header found in mpeg-4 video stream\n", ProgName); return MP4_INVALID_TRACK_ID; } // convert frame duration to canonical time scale // note zero value for frame duration signals variable rate video if (timeTicks == 0) { timeTicks = 1; } u_int32_t mp4FrameDuration = 0; if (VideoFrameRate) { mp4FrameDuration = (u_int32_t)(((double)Mp4TimeScale) / VideoFrameRate); } else if (frameDuration) { VideoFrameRate = frameDuration;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -