📄 h263plusvideostreamparser.cpp
字号:
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). * NOTE: This number MUST be > 0 * ppNextHeader - output parameter that upon return points to the location * of the next frame's head in the buffer * Outputs: * This function returns two pieces of information: * 1. The total number of bytes read. * 2. A Pointer to the header of the next frame. This pointer shall be NULL * for the last frame read. * /static int LoadNextH263Object( FILE *inputFileHandle, u_int8_t *frameBuffer, u_int32_t *frameBufferSize, u_int32_t additionalBytesNeeded, u_int8_t **ppNextHeader){ // This table and the following loop implements a state machine enabling // us to read bytes from the file untill (and inclusing) the requested // start code (00 00 8X) is found int8_t row = 0; u_int8_t *bufferStart = frameBuffer; // The buffer end which will allow the loop to leave place for // the additionalBytesNeeded u_int8_t *bufferEnd = frameBuffer + *frameBufferSize - additionalBytesNeeded - 1; // Initialize the states array, if it hasn't been initialized yet... if (!states[0][0]) { // One 00 was read states[0][0] = 1; // Two sequential 0x00 ware read states[1][0] = states[2][0] = 2; // A full start code was read states[2][128] = states[2][129] = states[2][130] = states[2][131] = -1; } // Read data from file into the output buffer until either a start code // is found, or the end of file has been reached. do { if (fread(frameBuffer, 1, 1, inputFileHandle) != 1){ // EOF or other error before we got a start code *ppNextHeader = NULL; *frameBufferSize = frameBuffer - bufferStart; return 1; } } while ((frameBuffer < bufferEnd) && // We have place in the buffer ((row = states[row][*(frameBuffer++)]) != -1)); // Start code was not found if (row != -1) { fprintf(stderr, "%s: Buffer too small (%u)\n", ProgName, bufferEnd - bufferStart + additionalBytesNeeded); return 0; } // Cool ... now we have a start code *ppNextHeader = frameBuffer - H263_STARTCODE_SIZE_BYTES; *frameBufferSize = frameBuffer - bufferStart + additionalBytesNeeded; // Now we just have to read the additionalBytesNeeded if(fread(frameBuffer, additionalBytesNeeded, 1, inputFileHandle) != 1) { /// We got a start code but can't read additionalBytesNeeded ... that's a fatal error fprintf(stderr, "%s: Invalid H263 bitstream\n", ProgName); return 0; } return 1;}/ * * ParseShortHeader - service routine that accepts a buffer containing a frame * header and extracts relevant codec information from it. * * NOTE: the first bit in the following commnets is 0 (zero). * * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | PSC (Picture Start Code=22 bits) | (TR=8 bits) | > * |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0| |1 0> * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * < (PTYPE=13 bits) | * <. . .|(FMT)|Z|. . . .| * +-+-+-+-+-+-+-+-+-+-+-+ * -> PTYPE.FMT contains a width/height identification * -> PTYPE.Z is 1 for P-Frames, 0 for I-Frames * Note: When FMT is 111, there is an extended PTYPE... * * Inputs: * headerBuffer - pointer to the current header buffer * outputInfoStruct - pointer to the structure receiving the data * Outputs: * This function returns a structure of important codec-specific * information (The Temporal Reference bits, width & height of the current * frame and the sync - or "frame type" - bit. It reports success or * failure to the calling function. * /static bool ParseShortHeader( u_int8_t *headerBuffer, H263INFO *outputInfoStruct){ u_int8_t fmt = 0; // Extract temporal reference (TR) from the buffer (bits 22-29 inclusive) outputInfoStruct->tr = (headerBuffer[2] << 6) & 0xC0; // 2 LS bits out of the 3rd byte outputInfoStruct->tr |= (headerBuffer[3] >> 2) & 0x3F; // 6 MS bits out of the 4th byte // Extract the FMT part of PTYPE from the buffer (bits 35-37 inclusive) fmt = (headerBuffer[4] >> 2) & 0x07; // bits 3-5 ouf of the 5th byte // If PTYPE is not supported, return a failure notice to the calling function // FIXME: PLUSPTYPE is not supported if (fmt == 0x07) { return false; } // If PTYPE is supported, calculate the current width and height according to // a predefined table if (!GetWidthAndHeight(fmt, &(outputInfoStruct->width), &(outputInfoStruct->height))) { return false; } // Extract the frame-type bit, which is the 9th bit of PTYPE (bit 38) outputInfoStruct->isSyncFrame = !(headerBuffer[4] & 0x02); return true;}/ * * GetMaxBitrate- service routine that accepts frame information and * derives bitrate information from it. This function uses a sliding window * technique to calculate the maximum bitrates in any window of 1 second * inside the file. * The sliding window is implemented with a table of bitrates for the last * second (30 entries - one entry per TR unit). * * Inputs: * ctx - context for this function * frameSize - the size of the current frame in bytes * frameTRDiff - the "duration" of the frame in TR units * Outputs: * This function returns the up-to-date maximum bitrate * /static void 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 ctx->tableIndex = (ctx->tableIndex + 1) % // Wrapping around the bitrateTable size ( 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 * Outputs: * The current frame's duration in milli-seconds * /static MP4Duration CalculateDuration(u_int8_t trDiff){ static u_int32_t nextTR = 0; // The next frame's presentation time in TR units static MP4Duration currentPT = 0; // The current frame's presentation time in milli-seconds MP4Duration nextPT; // The next frame's presentation time in milli-seconds MP4Duration duration; // The current frame's duration in milli-seconds nextTR += trDiff; // Calculate the next frame's presentation time, in milli-seconds nextPT = (nextTR * 1001) / H263_BASIC_FRAME_RATE; // The frame's duration is the difference between the next presentation // time and the current presentation time. duration = nextPT - currentPT; // "Remember" the next presentation time for the next time this function is // called currentPT = nextPT; return duration;}static bool 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;}static u_int8_t GetTRDifference(u_int8_t nextTR, u_int8_t currentTR){ if (currentTR > nextTR) { // Wrap around 255... return nextTR + (256 - currentTR); } else { return nextTR - currentTR; }}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -