📄 h263plusvideostreamparser.cpp
字号:
void H263plusVideoStreamParser::GetMaxBitrate( MaxBitrate_CTX *ctx, u_int32_t frameSize, u_int8_t frameTRDiff){ if (frameTRDiff == 0) return; // Calculate the current frame's bitrate as bits per TR unit (round the result // upwards) u_int32_t frameBitrate = frameSize * 8 / frameTRDiff + 1; // for each TRdiff received, while (frameTRDiff--) { // Subtract the oldest bitrate entry from the current bitrate ctx->windowBitrate -= ctx->bitrateTable[ctx->tableIndex]; // Update the oldest bitrate entry with the current frame's bitrate ctx->bitrateTable[ctx->tableIndex] = frameBitrate; // Add the current frame's bitrate to the current bitrate ctx->windowBitrate += frameBitrate; // Check if we have a new maximum bitrate if (ctx->windowBitrate > ctx->maxBitrate) { ctx->maxBitrate = ctx->windowBitrate; } // Advance the table index // Wrapping around the bitrateTable size ctx->tableIndex = (ctx->tableIndex + 1) % ( sizeof(ctx->bitrateTable) / sizeof(ctx->bitrateTable[0]) ); }}////////////////////////////////////////////////////////////////////////////////// CalculateDuration - service routine that calculates the current frame's// duration in milli-seconds using it's duration in TR units.// - In order not to accumulate the calculation error, we are using the TR// duration to calculate the current and the next frame's presentation time in// milli-seconds.//// Inputs: trDiff - The current frame's duration in TR units// Return: The current frame's duration in milli-seconds////////////////////////////////////////////////////////////////////////////////u_int64_t H263plusVideoStreamParser::CalculateDuration(u_int8_t trDiff){ //static u_int32_t nextTR = 0; // The next frame's presentation time in TR units //static u_int64_t currentPT = 0; // The current frame's presentation time in milli-seconds u_int64_t nextPT; // The next frame's presentation time in milli-seconds u_int64_t duration; // The current frame's duration in milli-seconds fnextTR += trDiff; // Calculate the next frame's presentation time, in milli-seconds nextPT = (fnextTR * 1001) / H263_BASIC_FRAME_RATE; // The frame's duration is the difference between the next presentation // time and the current presentation time. duration = nextPT - fcurrentPT; // "Remember" the next presentation time for the next time this function is called fcurrentPT = nextPT; return duration;}////////////////////////////////////////////////////////////////////////////////bool H263plusVideoStreamParser::GetWidthAndHeight( u_int8_t fmt, u_int16_t *width, u_int16_t *height){ // The 'fmt' corresponds to bits 5-7 of the PTYPE static struct { u_int16_t width; u_int16_t height; } dimensionsTable[8] = { { 0, 0 }, // 000 - 0 - forbidden, generates an error { 128, 96 }, // 001 - 1 - Sub QCIF { 176, 144 }, // 010 - 2 - QCIF { 352, 288 }, // 011 - 3 - CIF { 704, 576 }, // 100 - 4 - 4CIF { 1409, 1152 }, // 101 - 5 - 16CIF { 0, 0 }, // 110 - 6 - reserved, generates an error { 0, 0 } // 111 - 7 - extended, not supported by profile 0 }; if (fmt > 7) return false; *width = dimensionsTable[fmt].width; *height = dimensionsTable[fmt].height; if (*width == 0) return false; return true;}////////////////////////////////////////////////////////////////////////////////u_int8_t H263plusVideoStreamParser::GetTRDifference( u_int8_t nextTR, u_int8_t currentTR){ if (currentTR > nextTR) { // Wrap around 255... return nextTR + (256 - currentTR); } else { return nextTR - currentTR; }}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// this is the h263.c file of MPEG4IP mp4creator/*#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);static char states[3][256];/ * * 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(¤tInfo, 0, sizeof(currentInfo)); memset(&maxBitrateCtx, 0, sizeof(maxBitrateCtx)); memset(states, 0, sizeof(states)); 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -