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

📄 h263.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * 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):  *              Ximpo Group Ltd.		mp4v2@ximpo.com *              Bill May wmay@cisco.com */#include "mp4creator.h"// Default timescale for H.263 (1000ms)#define H263_TIMESCALE 1000// Default H263 frame rate (30fps)#define H263_BASIC_FRAME_RATE 30// Minimum number of bytes needed to parse an H263 header#define H263_REQUIRE_HEADER_SIZE_BYTES 5// Number of bytes the start code requries#define H263_STARTCODE_SIZE_BYTES 3// This is the input buffer's size. It should contain// 1 frame with the following start code#define H263_BUFFER_SIZE 256 * 1024// The default max different (in %) betwqeen max and average bitrates#define H263_DEFAULT_CBR_TOLERANCE  10// The following structure holds information extracted from each frame's header:typedef struct _H263INFO {  u_int8_t  tr;                 // Temporal Reference, used in duration calculation  u_int16_t width;              // Width of the picture  u_int16_t height;             // Height of the picture  bool      isSyncFrame;        // Frame type (true = I frame = "sync" frame)} H263INFO;// Context for the GetMaxBitrate functiontypedef struct _MaxBitrate_CTX {  u_int32_t  bitrateTable[H263_BASIC_FRAME_RATE];// Window of 1 second  u_int32_t  windowBitrate;              // The bitrate of the current window  u_int32_t  maxBitrate;                 // The up-to-date maximum bitrate  u_int32_t  tableIndex;                 // The next TR unit to update} MaxBitrate_CTX;// Forward declarations:static int LoadNextH263Object(  FILE           *inputFileHandle,                                u_int8_t       *frameBuffer,                                u_int32_t      *frameBufferSize,                                u_int32_t       additionalBytesNeeded,                                u_int8_t      **ppNextHeader);static bool ParseShortHeader(   u_int8_t       *headerBuffer,                                H263INFO       *outputInfoStruct);static u_int8_t GetTRDifference(u_int8_t        nextTR,                                u_int8_t        currentTR);static void GetMaxBitrate(      MaxBitrate_CTX *ctx,                                u_int32_t       frameSize,                                u_int8_t        frameTRDiff);static MP4Duration CalculateDuration(u_int8_t   trDiff);static bool GetWidthAndHeight(  u_int8_t        fmt,                                u_int16_t      *width,                                u_int16_t      *height);/* * H263Creator - Main function * Inputs: *      outputFileHandle - The handle of the output file *      inputFileHandle - The handle of the input file *      Codec-specific parameters: *              H263Level - H.263 Level used for this track *              H263Profile - H.263 Profile used for this track *              H263Bitrates - A Parameter indicating whether the function *                             should calculate H263 bitrates or not. *              cbrTolerance - CBR tolerance indicates when to set the *                             average bitrate. * Outputs: *      This function returns either the track ID of the newly added track upon *      success or a predefined value representing an erroneous state. */MP4TrackId H263Creator(MP4FileHandle outputFileHandle,                       FILE*         inputFileHandle,                       u_int8_t      h263Profile,                       u_int8_t      h263Level,                       bool          h263Bitrates,                       u_int8_t      cbrTolerance){  H263INFO       nextInfo;   // Holds information about the next frame  H263INFO       currentInfo;// Holds information about the current frame  MaxBitrate_CTX maxBitrateCtx;// Context for the GetMaxBitrate function  memset(&nextInfo, 0, sizeof(nextInfo));  memset(&currentInfo, 0, sizeof(currentInfo));  memset(&maxBitrateCtx, 0, sizeof(maxBitrateCtx));  u_int8_t       frameBuffer[H263_BUFFER_SIZE]; // The input buffer                 // Pointer which tells LoadNextH263Object where to read data to  u_int8_t*      pFrameBuffer = frameBuffer + H263_REQUIRE_HEADER_SIZE_BYTES;  u_int32_t      frameSize;        // The current frame size                                // Pointer to receive address of the header data  u_int8_t*      pCurrentHeader = pFrameBuffer;  MP4Duration    currentDuration;  // The current frame's duration  u_int8_t       trDifference;     // The current TR difference                                   // The previous TR difference  u_int8_t       prevTrDifference = H263_BASIC_FRAME_RATE;  MP4Duration    totalDuration = 0;// Duration accumulator  MP4Duration    avgBitrate;       // Average bitrate  u_int64_t      totalBytes = 0;   // Size accumulator  MP4TrackId     trackId = MP4_INVALID_TRACK_ID; // Our MP4 track  bool           stay = true;      // loop flag  while (stay) {    currentInfo = nextInfo;    memmove(frameBuffer, pCurrentHeader, H263_REQUIRE_HEADER_SIZE_BYTES);    frameSize = H263_BUFFER_SIZE - H263_REQUIRE_HEADER_SIZE_BYTES;    // Read 1 frame and the next frame's header from the file.    // For the first frame, only the first frame's header is returned.    // For the last frame, only the last frame's data is returned.    if (! LoadNextH263Object(inputFileHandle, pFrameBuffer, &frameSize,          H263_REQUIRE_HEADER_SIZE_BYTES - H263_STARTCODE_SIZE_BYTES,          &pCurrentHeader))      break; // Fatal error ...    if (pCurrentHeader) {      // Parse the returned frame header (if any)      if (!ParseShortHeader(pCurrentHeader, &nextInfo))        break; // Fatal error      trDifference = GetTRDifference(nextInfo.tr, currentInfo.tr);    } else {      // This is the last frame ... we have to fake the trDifference ...      trDifference = 1;      // No header data has been read at this iteration, so we have to manually      // add the frame's header we read at the previous iteration.      // Note that LoadNextH263Object returns the number of bytes read, which      // are the current frame's data and the next frame's header      frameSize += H263_REQUIRE_HEADER_SIZE_BYTES;      // There is no need for the next iteration ...      stay = false;    }    // If this is the first iteration ...    if (currentInfo.width == 0) {      // If we have more data than just the header      if ((frameSize > H263_REQUIRE_HEADER_SIZE_BYTES) ||          !pCurrentHeader)  // Or no header at all        break;     // Fatal error      else        continue;  // We have only the first frame's header ...    }    if (trackId == MP4_INVALID_TRACK_ID) {      //  If a track has not been added yet, add the track to the file.      trackId = MP4AddH263VideoTrack(outputFileHandle, H263_TIMESCALE,          0, currentInfo.width, currentInfo.height,          h263Level, h263Profile, 0, 0);      if (trackId == MP4_INVALID_TRACK_ID)        break; // Fatal error    }    // calculate the current frame duration    currentDuration = CalculateDuration(trDifference);    // Write the current frame to the file.    if (!MP4WriteSample(outputFileHandle, trackId, frameBuffer, frameSize,          currentDuration, 0, currentInfo.isSyncFrame))      break; // Fatal error    // Accumulate the frame's size and duration for avgBitrate calculation    totalDuration += currentDuration;    totalBytes += frameSize;    //  If needed, recalculate bitrate information    if (h263Bitrates)      GetMaxBitrate(&maxBitrateCtx, frameSize, prevTrDifference);    prevTrDifference = trDifference;  } // while (stay)  // If this is the last frame,  if (!stay) {    // If needed and possible, update bitrate information in the file    if (h263Bitrates && totalDuration) {      avgBitrate = (totalBytes * 8 * H263_TIMESCALE) / totalDuration;      if (cbrTolerance == 0)        cbrTolerance = H263_DEFAULT_CBR_TOLERANCE;      // Same as: if (maxBitrate / avgBitrate > (cbrTolerance + 100) / 100.0)      if (maxBitrateCtx.maxBitrate * 100 > (cbrTolerance + 100) * avgBitrate)        avgBitrate = 0;      MP4SetH263Bitrates(outputFileHandle, trackId,          avgBitrate, maxBitrateCtx.maxBitrate);    }    // Return the newly added track ID    return trackId;  }  // If we got to here... something went wrong ...  fprintf(stderr,    "%s: Could not parse input file, invalid video stream?\n", ProgName);  // Upon failure, delete the newly added track if it has been added  if (trackId != MP4_INVALID_TRACK_ID) {    MP4DeleteTrack(outputFileHandle, trackId);  }  return MP4_INVALID_TRACK_ID;}/* * LoadNextH263Object - service routine that reads a single frame from the input * file. It shall fill the input buffer with data up until - and including - the * next start code and shall report back both the number of bytes read and a * pointer to the next start code. The first call to this function shall only * yield a pointer with 0 data bytes and the last call to this function shall * only yield data bytes with a NULL pointer as the next header. * * TODO: This function only supports valid bit streams. Upon error, it fails * without the possibility to recover. A Better idea would be to skip frames * until a parsable frame is read from the file. * * Parameters: *      inputFileHandle - The handle of the input file *      frameBuffer - buffer where to place read data *      frameBufferSize - in/out parameter indicating the size of the buffer on *                          entry and the number of bytes copied to the buffer upon *                          return *      additionalBytesNeeded - indicates how many additional bytes are to be read *                          from the next frame's header (over the 3 bytes that *                          are already read).

⌨️ 快捷键说明

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