mpeg4.cpp
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:12k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /*
- * 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-2002. All Rights Reserved.
- *
- * Contributor(s):
- * Dave Mackie dmackie@cisco.com
- */
- /*
- * Notes:
- * - file formatted with tabstops == 4 spaces
- */
- #include <mp4av_common.h>
- extern "C" bool MP4AV_Mpeg4ParseVosh(
- u_int8_t* pVoshBuf,
- u_int32_t voshSize,
- u_int8_t* pProfileLevel)
- {
- CMemoryBitstream vosh;
- vosh.SetBytes(pVoshBuf, voshSize);
- try {
- vosh.GetBits(32); // start code
- *pProfileLevel = vosh.GetBits(8);
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- extern "C" bool MP4AV_Mpeg4CreateVosh(
- u_int8_t** ppBytes,
- u_int32_t* pNumBytes,
- u_int8_t profileLevel)
- {
- CMemoryBitstream vosh;
- try {
- if (*ppBytes) {
- // caller must guarantee buffer against overrun
- memset((*ppBytes) + (*pNumBytes), 0, 5);
- vosh.SetBytes(*ppBytes, (*pNumBytes) + 5);
- vosh.SetBitPosition((*pNumBytes) << 3);
- } else {
- vosh.AllocBytes(5);
- }
- vosh.PutBits(MP4AV_MPEG4_SYNC, 24);
- vosh.PutBits(MP4AV_MPEG4_VOSH_START, 8);
- vosh.PutBits(profileLevel, 8);
- *ppBytes = vosh.GetBuffer();
- *pNumBytes = vosh.GetNumberOfBytes();
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- extern "C" bool MP4AV_Mpeg4CreateVo(
- u_int8_t** ppBytes,
- u_int32_t* pNumBytes,
- u_int8_t objectId)
- {
- CMemoryBitstream vo;
- try {
- if (*ppBytes) {
- // caller must guarantee buffer against overrun
- memset((*ppBytes) + (*pNumBytes), 0, 9);
- vo.SetBytes(*ppBytes, *pNumBytes + 9);
- vo.SetBitPosition((*pNumBytes) << 3);
- } else {
- vo.AllocBytes(9);
- }
- vo.PutBits(MP4AV_MPEG4_SYNC, 24);
- vo.PutBits(MP4AV_MPEG4_VO_START, 8);
- vo.PutBits(0x08, 8); // no verid, priority, or signal type
- vo.PutBits(MP4AV_MPEG4_SYNC, 24);
- vo.PutBits(objectId - 1, 8);
- *ppBytes = vo.GetBuffer();
- *pNumBytes = vo.GetNumberOfBytes();
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- extern "C" bool MP4AV_Mpeg4ParseVol(
- u_int8_t* pVolBuf,
- u_int32_t volSize,
- u_int8_t* pTimeBits,
- u_int16_t* pTimeTicks,
- u_int16_t* pFrameDuration,
- u_int16_t* pFrameWidth,
- u_int16_t* pFrameHeight)
- {
- CMemoryBitstream vol;
- vol.SetBytes(pVolBuf, volSize);
- try {
- vol.SkipBits(32); // start code
- vol.SkipBits(1); // random accessible vol
- vol.SkipBits(8); // object type id
- u_int8_t verid = 0;
- if (vol.GetBits(1)) { // is object layer id
- verid = vol.GetBits(4); // object layer verid
- vol.SkipBits(3); // object layer priority
- }
- if (vol.GetBits(4) == 0xF) { // aspect ratio info
- vol.SkipBits(8); // par width
- vol.SkipBits(8); // par height
- }
- if (vol.GetBits(1)) { // vol control parameters
- vol.SkipBits(2); // chroma format
- vol.SkipBits(1); // low delay
- if (vol.GetBits(1)) { // vbv parameters
- vol.SkipBits(15); // first half bit rate
- vol.SkipBits(1); // marker bit
- vol.SkipBits(15); // latter half bit rate
- vol.SkipBits(1); // marker bit
- vol.SkipBits(15); // first half vbv buffer size
- vol.SkipBits(1); // marker bit
- vol.SkipBits(3); // latter half vbv buffer size
- vol.SkipBits(11); // first half vbv occupancy
- vol.SkipBits(1); // marker bit
- vol.SkipBits(15); // latter half vbv occupancy
- vol.SkipBits(1); // marker bit
- }
- }
- u_int8_t shape = vol.GetBits(2); // object layer shape
- if (shape == 3 /* GRAYSCALE */ && verid != 1) {
- vol.SkipBits(4); // object layer shape extension
- }
- vol.SkipBits(1); // marker bit
- *pTimeTicks = vol.GetBits(16); // vop time increment resolution
- u_int8_t i;
- u_int32_t powerOf2 = 1;
- for (i = 0; i < 16; i++) {
- if (*pTimeTicks < powerOf2) {
- break;
- }
- powerOf2 <<= 1;
- }
- *pTimeBits = i;
- vol.SkipBits(1); // marker bit
- if (vol.GetBits(1)) { // fixed vop rate
- // fixed vop time increment
- *pFrameDuration = vol.GetBits(*pTimeBits);
- } else {
- *pFrameDuration = 0;
- }
- if (shape == 0 /* RECTANGULAR */) {
- vol.SkipBits(1); // marker bit
- *pFrameWidth = vol.GetBits(13); // object layer width
- vol.SkipBits(1); // marker bit
- *pFrameHeight = vol.GetBits(13);// object layer height
- vol.SkipBits(1); // marker bit
- } else {
- *pFrameWidth = 0;
- *pFrameHeight = 0;
- }
- // there's more, but we don't need it
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- extern "C" bool MP4AV_Mpeg4CreateVol(
- u_int8_t** ppBytes,
- u_int32_t* pNumBytes,
- u_int8_t profile,
- float frameRate,
- bool shortTime,
- bool variableRate,
- u_int16_t width,
- u_int16_t height,
- u_int8_t quantType,
- u_int8_t* pTimeBits)
- {
- CMemoryBitstream vol;
- try {
- if (*ppBytes) {
- // caller must guarantee buffer against overrun
- memset((*ppBytes) + (*pNumBytes), 0, 20);
- vol.SetBytes(*ppBytes, *pNumBytes + 20);
- vol.SetBitPosition((*pNumBytes) << 3);
- } else {
- vol.AllocBytes(20);
- }
- /* VOL - Video Object Layer */
- vol.PutBits(MP4AV_MPEG4_SYNC, 24);
- vol.PutBits(MP4AV_MPEG4_VOL_START, 8);
- /* 1 bit - random access = 0 (1 only if every VOP is an I frame) */
- vol.PutBits(0, 1);
- /*
- * 8 bits - type indication
- * = 1 (simple profile)
- * = 4 (main profile)
- */
- vol.PutBits(profile, 8);
- /* 1 bit - is object layer id = 1 */
- vol.PutBits(1, 1);
- /* 4 bits - visual object layer ver id = 2 */
- vol.PutBits(2, 4);
- /* 3 bits - visual object layer priority = 1 */
- vol.PutBits(1, 3);
- /* 4 bits - aspect ratio info = 1 (square pixels) */
- vol.PutBits(1, 4);
- /* 1 bit - VOL control params = 0 */
- vol.PutBits(0, 1);
- /* 2 bits - VOL shape = 0 (rectangular) */
- vol.PutBits(0, 2);
- /* 1 bit - marker = 1 */
- vol.PutBits(1, 1);
- u_int16_t ticks;
- if (shortTime /* && frameRate == (float)((int)frameRate) */) {
- ticks = (u_int16_t)(frameRate + 0.5);
- } else {
- ticks = 30000;
- }
- /* 16 bits - VOP time increment resolution */
- vol.PutBits(ticks, 16);
- /* 1 bit - marker = 1 */
- vol.PutBits(1, 1);
- u_int8_t rangeBits = 1;
- while (ticks > (1 << rangeBits)) {
- rangeBits++;
- }
- if (pTimeBits) {
- *pTimeBits = rangeBits;
- }
- /* 1 bit - fixed vop rate = 0 or 1 */
- if (variableRate) {
- vol.PutBits(0, 1);
- } else {
- vol.PutBits(1, 1);
- u_int16_t frameDuration =
- (u_int16_t)((float)ticks / frameRate);
- /* 1-16 bits - fixed vop time increment in ticks */
- vol.PutBits(frameDuration, rangeBits);
- }
- /* 1 bit - marker = 1 */
- vol.PutBits(1, 1);
- /* 13 bits - VOL width */
- vol.PutBits(width, 13);
- /* 1 bit - marker = 1 */
- vol.PutBits(1, 1);
- /* 13 bits - VOL height */
- vol.PutBits(height, 13);
- /* 1 bit - marker = 1 */
- vol.PutBits(1, 1);
- /* 1 bit - interlaced = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - overlapped block motion compensation disable = 1 */
- vol.PutBits(1, 1);
- /* 2 bits - sprite usage = 0 */
- vol.PutBits(0, 2);
- /* 1 bit - not 8 bit pixels = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - quant type = 0 */
- vol.PutBits(quantType, 1);
- if (quantType) {
- /* 1 bit - load intra quant mat = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - load inter quant mat = 0 */
- vol.PutBits(0, 1);
- }
- /* 1 bit - quarter pixel = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - complexity estimation disable = 1 */
- vol.PutBits(1, 1);
- /* 1 bit - resync marker disable = 1 */
- vol.PutBits(1, 1);
- /* 1 bit - data partitioned = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - newpred = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - reduced resolution vop = 0 */
- vol.PutBits(0, 1);
- /* 1 bit - scalability = 0 */
- vol.PutBits(0, 1);
- /* pad to byte boundary with 0 then as many 1's as needed */
- vol.PutBits(0, 1);
- if ((vol.GetBitPosition() & 7) != 0) {
- vol.PutBits(0xFF, 8 - (vol.GetBitPosition() & 7));
- }
- *ppBytes = vol.GetBuffer();
- *pNumBytes = vol.GetBitPosition() >> 3;
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- extern "C" bool MP4AV_Mpeg4ParseGov(
- u_int8_t* pGovBuf,
- u_int32_t govSize,
- u_int8_t* pHours,
- u_int8_t* pMinutes,
- u_int8_t* pSeconds)
- {
- CMemoryBitstream gov;
- gov.SetBytes(pGovBuf, govSize);
- try {
- gov.SkipBits(32); // start code
- *pHours = gov.GetBits(5);
- *pMinutes = gov.GetBits(6);
- gov.SkipBits(1); // marker bit
- *pSeconds = gov.GetBits(6);
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- extern "C" bool MP4AV_Mpeg4ParseVop(
- u_int8_t* pVopBuf,
- u_int32_t vopSize,
- u_char* pVopType,
- u_int8_t timeBits,
- u_int16_t timeTicks,
- u_int32_t* pVopTimeIncrement)
- {
- CMemoryBitstream vop;
- vop.SetBytes(pVopBuf, vopSize);
- try {
- vop.SkipBits(32); // skip start code
- switch (vop.GetBits(2)) {
- case 0:
- /* Intra */
- *pVopType = 'I';
- break;
- case 1:
- /* Predictive */
- *pVopType = 'P';
- break;
- case 2:
- /* Bidirectional Predictive */
- *pVopType = 'B';
- break;
- case 3:
- /* Sprite */
- *pVopType = 'S';
- break;
- }
- if (!pVopTimeIncrement) {
- return true;
- }
- u_int8_t numSecs = 0;
- while (vop.GetBits(1) != 0) {
- numSecs++;
- }
- vop.SkipBits(1); // skip marker
- u_int16_t numTicks = vop.GetBits(timeBits);
- *pVopTimeIncrement = (numSecs * timeTicks) + numTicks;
- }
- catch (int e) {
- return false;
- }
- return true;
- }
- // Map from ISO IEC 14496-2:2000 Appendix G
- // to ISO IEC 14496-1:2001 8.6.4.2 Table 6
- extern "C" u_int8_t
- MP4AV_Mpeg4VideoToSystemsProfileLevel(u_int8_t videoProfileLevel)
- {
- switch (videoProfileLevel) {
- // Simple Profile
- case 0x01: // L1
- return 0x03;
- case 0x02: // L2
- return 0x02;
- case 0x03: // L3
- return 0x01;
- // Simple Scalable Profile
- case 0x11: // L1
- return 0x05;
- case 0x12: // L2
- return 0x04;
- // Core Profile
- case 0x21: // L1
- return 0x07;
- case 0x22: // L2
- return 0x06;
- // Main Profile
- case 0x32: // L2
- return 0x0A;
- case 0x33: // L3
- return 0x09;
- case 0x34: // L4
- return 0x08;
- // N-bit Profile
- case 0x42: // L2
- return 0x0B;
- // Scalable Texture
- case 0x51: // L1
- return 0x12;
- case 0x52: // L2
- return 0x11;
- case 0x53: // L3
- return 0x10;
- // Simple Face Animation Profile
- case 0x61: // L1
- return 0x14;
- case 0x62: // L2
- return 0x13;
- // Simple FBA Profile
- case 0x63: // L1
- case 0x64: // L2
- return 0xFE;
- // Basic Animated Texture Profile
- case 0x71: // L1
- return 0x0F;
- case 0x72: // L2
- return 0x0E;
- // Hybrid Profile
- case 0x81: // L1
- return 0x0D;
- case 0x82: // L2
- return 0x0C;
- // Advanced Real Time Simple Profile
- case 0x91: // L1
- case 0x92: // L2
- case 0x93: // L3
- case 0x94: // L4
- // Core Scalable Profile
- case 0xA1: // L1
- case 0xA2: // L2
- case 0xA3: // L3
- // Advanced Coding Efficiency Profle
- case 0xB1: // L1
- case 0xB2: // L2
- case 0xB3: // L3
- case 0xB4: // L4
- // Advanced Core Profile
- case 0xC1: // L1
- case 0xC2: // L2
- // Advanced Scalable Texture Profile
- case 0xD1: // L1
- case 0xD2: // L2
- case 0xD3: // L3
- // from draft amendments
- // Simple Studio
- case 0xE1: // L1
- case 0xE2: // L2
- case 0xE3: // L3
- case 0xE4: // L4
- // Core Studio Profile
- case 0xE5: // L1
- case 0xE6: // L2
- case 0xE7: // L3
- case 0xE8: // L4
- // Advanced Simple Profile
- case 0xF1: // L0
- case 0xF2: // L1
- case 0xF3: // L2
- case 0xF4: // L3
- case 0xF5: // L4
- // Fine Granularity Scalable Profile
- case 0xF6: // L0
- case 0xF7: // L1
- case 0xF8: // L2
- case 0xF9: // L3
- case 0xFA: // L4
- default:
- return 0xFE;
- }
- }
- extern "C" u_char MP4AV_Mpeg4GetVopType(u_int8_t* pVopBuf, u_int32_t vopSize)
- {
- u_char vopType;
- if (MP4AV_Mpeg4ParseVop(pVopBuf, vopSize, &vopType, 0, 0, NULL)) {
- return vopType;
- }
- return 0;
- }