📄 mpeg3.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. 2002 - 2004. All Rights Reserved. * * Contributor(s): * Bill May (wmay@cisco.com) */#include "mpeg4ip.h"#include "mp4av.h"//#define DEBUG_MPEG3_HINT 1static double mpeg3_frame_rate_table[16] ={ 0.0, /* Pad */ 24000.0/1001.0, /* Official frame rates */ 24.0, 25.0, 30000.0/1001.0, 30.0, 50.0, ((60.0*1000.0)/1001.0), 60.0, 1, /* Unofficial economy rates */ 5, 10, 12, 15, 0, 0,};#define MPEG3_START_CODE_PREFIX 0x000001#define MPEG3_SEQUENCE_START_CODE 0x000001b3#define MPEG3_PICTURE_START_CODE 0x00000100#define MPEG3_GOP_START_CODE 0x000001b8#define MPEG3_EXT_START_CODE 0x000001b5#define MPEG3_SLICE_MIN_START 0x00000101#define MPEG3_SLICE_MAX_START 0x000001af#define SEQ_ID 1extern "C" int MP4AV_Mpeg3ParseSeqHdr (const uint8_t *pbuffer, uint32_t buflen, int *have_mpeg2, uint32_t *height, uint32_t *width, double *frame_rate, double *bitrate, double *aspect_ratio, uint8_t *mpeg2_profile){ uint32_t aspect_code; uint32_t framerate_code; uint32_t bitrate_int; uint32_t bitrate_ext;#if 1 uint32_t scode, ix; int found = -1; if (have_mpeg2 != NULL) *have_mpeg2 = 0; if (mpeg2_profile != NULL) *mpeg2_profile = 0; buflen -= 6; bitrate_int = 0; for (ix = 0; ix < buflen; ix++, pbuffer++) { scode = (pbuffer[0] << 24) | (pbuffer[1] << 16) | (pbuffer[2] << 8) | pbuffer[3]; if (scode == MPEG3_SEQUENCE_START_CODE) { pbuffer += sizeof(uint32_t); if (width != NULL) { *width = (pbuffer[0]); *width <<= 4; *width |= ((pbuffer[1] >> 4) &0xf); } if (height != NULL) { *height = (pbuffer[1] & 0xf); *height <<= 8; *height |= pbuffer[2]; } aspect_code = (pbuffer[3] >> 4) & 0xf; if (aspect_ratio != NULL) { switch (aspect_code) { default: *aspect_ratio = 1.0; break; case 2: *aspect_ratio = 4.0 / 3.0; break; case 3: *aspect_ratio = 16.0 / 9.0; break; case 4: *aspect_ratio = 2.21; break; } } framerate_code = pbuffer[3] & 0xf; if (frame_rate != NULL) { *frame_rate = mpeg3_frame_rate_table[framerate_code]; } // 18 bits bitrate_int = (pbuffer[4] << 10) | (pbuffer[5] << 2) | ((pbuffer[6] >> 6) & 0x3); if (bitrate != NULL) { *bitrate = bitrate_int; *bitrate *= 400.0; } ix += sizeof(uint32_t) + 7; pbuffer += 7; found = 0; } else if (found == 0) { if (scode == MPEG3_EXT_START_CODE) { pbuffer += sizeof(uint32_t); ix += sizeof(uint32_t); switch ((pbuffer[0] >> 4) & 0xf) { case SEQ_ID: if (have_mpeg2 != NULL) *have_mpeg2 = 1; if (mpeg2_profile != NULL) *mpeg2_profile = ((pbuffer[0] & 0xf) << 4) | ((pbuffer[1] >> 4) & 0xf); if (height != NULL) { *height = ((pbuffer[1] & 0x1) << 13) | ((pbuffer[2] & 0x80) << 5) | (*height & 0x0fff); } if (width != NULL) *width = (((pbuffer[2] >> 5) & 0x3) << 12) | (*width & 0x0fff); bitrate_ext = (pbuffer[2] & 0x1f) << 7; bitrate_ext |= (pbuffer[3] >> 1) & 0x7f; bitrate_int |= (bitrate_ext << 18); if (bitrate != NULL) { *bitrate = bitrate_int; *bitrate *= 400.0; } break; default: break; } pbuffer++; ix++; } else if (scode == MPEG3_PICTURE_START_CODE) { return found; } } } return found;#else // if you want to do the whole frame int ix; CBitstream bs(pbuffer, buflen); try { while (bs.PeekBits(32) != MPEG3_SEQUENCE_START_CODE) { bs.GetBits(8); } bs.GetBits(32); // start code *height = bs.GetBits(12); *width = bs.GetBits(12); aspect_code = bs.GetBits(4); if (aspect_ratio != NULL) { switch (aspect_code) { default: *aspect_ratio = 1.0; break; case 2: *aspect_ratio = 4.0 / 3.0; break; case 3: *aspect_ratio = 16.0 / 9.0; break; case 4: *aspect_ratio = 2.21; break; } } framerate_code = bs.GetBits(4); *frame_rate = mpeg3_frame_rate_table[framerate_code]; bs.GetBits(18); // bitrate bs.GetBits(1); // marker bit bs.GetBits(10); // vbv buffer bs.GetBits(1); // constrained params if (bs.GetBits(1)) { // intra_quantizer_matrix for (ix = 0; ix < 64; ix++) { bs.GetBits(8); } } if (bs.GetBits(1)) { // non_intra_quantizer_matrix for (ix = 0; ix < 64; ix++) { bs.GetBits(8); } } } catch (...) { return false; } return true;#endif}extern "C" int MP4AV_Mpeg3PictHdrType (const uint8_t *pbuffer){ pbuffer += sizeof(uint32_t); return ((pbuffer[1] >> 3) & 0x7);}extern "C" uint16_t MP4AV_Mpeg3PictHdrTempRef (const uint8_t *pbuffer){ pbuffer += sizeof(uint32_t); return ((pbuffer[0] << 2) | ((pbuffer[1] >> 6) & 0x3));}extern "C" int MP4AV_Mpeg3FindNextStart (const uint8_t *pbuffer, uint32_t buflen, uint32_t *optr, uint32_t *scode){ uint32_t value; uint32_t offset; if (buflen < 4) return -1; for (offset = 0; offset < buflen - 3; offset++, pbuffer++) {#ifdef WORDS_BIGENDIAN value = *(uint32_t *)pbuffer >> 8;#else value = (pbuffer[0] << 16) | (pbuffer[1] << 8) | (pbuffer[2] << 0); #endif if (value == MPEG3_START_CODE_PREFIX) { *optr = offset; *scode = (value << 8) | pbuffer[3]; return 0; } } return -1;}extern "C" int MP4AV_Mpeg3FindNextSliceStart (const uint8_t *pbuffer, uint32_t startoffset, uint32_t buflen, uint32_t *slice_offset){ uint32_t slicestart, code; while (MP4AV_Mpeg3FindNextStart(pbuffer + startoffset, buflen - startoffset, &slicestart, &code) >= 0) {#ifdef DEBUG_MPEG3_HINT printf("Code %x at offset %d\n", code, startoffset + slicestart);#endif if ((code >= MPEG3_SLICE_MIN_START) && (code <= MPEG3_SLICE_MAX_START)) { *slice_offset = slicestart + startoffset; return 0; } startoffset += slicestart + 4; } return -1;} extern "C" int MP4AV_Mpeg3FindPictHdr (const uint8_t *pbuffer, uint32_t buflen, int *frame_type){ uint32_t value; uint32_t offset; int ftype; for (offset = 0; offset < buflen; offset++, pbuffer++) { value = (pbuffer[0] << 24) | (pbuffer[1] << 16) | (pbuffer[2] << 8) | pbuffer[3]; if (value == MPEG3_PICTURE_START_CODE) { ftype = MP4AV_Mpeg3PictHdrType(pbuffer); if (frame_type != NULL) *frame_type = ftype; return offset; } } return -1;}extern "C" bool Mpeg12Hinter (MP4FileHandle mp4file, MP4TrackId trackid, uint16_t maxPayloadSize){ uint32_t numSamples, maxSampleSize; uint8_t videoType; uint8_t rfc2250[4], rfc2250_2; uint32_t offset; uint32_t scode; int have_seq; bool stop; uint8_t *buffer, *pbuffer; uint8_t *pstart; uint8_t type; uint32_t next_slice, prev_slice; bool slice_at_begin; uint32_t sampleSize; MP4SampleId sid; MP4TrackId hintTrackId; numSamples = MP4GetTrackNumberOfSamples(mp4file, trackid); maxSampleSize = MP4GetTrackMaxSampleSize(mp4file, trackid); if (numSamples == 0) return false; videoType = MP4GetTrackEsdsObjectTypeId(mp4file, trackid); if (videoType != MP4_MPEG1_VIDEO_TYPE && videoType != MP4_MPEG2_VIDEO_TYPE) { return false; } hintTrackId = MP4AddHintTrack(mp4file, trackid); if (hintTrackId == MP4_INVALID_TRACK_ID) { return false; } uint8_t payload = 32; if (MP4SetHintTrackRtpPayload(mp4file, hintTrackId, "MPV", &payload, 0) == false) { MP4DeleteTrack(mp4file, hintTrackId); return false; } buffer = (uint8_t *)malloc(maxSampleSize); if (buffer == NULL) { MP4DeleteTrack(mp4file, hintTrackId); return false; } maxPayloadSize -= 24; // this is for the 4 byte header
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -