📄 h263plusvideostreamparser.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**********/// "liveMedia"// Copyright (c) 1996-2006 Live Networks, Inc. All rights reserved.// Author Bernhard Feiten// A filter that breaks up an H.263plus video stream into frames.// Based on MPEG4IP/mp4creator/h263.c#include "H263plusVideoStreamParser.hh"#include "H263plusVideoStreamFramer.hh"//#include <string.h>//#include "GroupsockHelper.hh"H263plusVideoStreamParser::H263plusVideoStreamParser( H263plusVideoStreamFramer* usingSource, FramedSource* inputSource) : StreamParser(inputSource, FramedSource::handleClosure, usingSource, &H263plusVideoStreamFramer::continueReadProcessing, usingSource), fUsingSource(usingSource), fnextTR(0), fcurrentPT(0){ memset(fStates, 0, sizeof(fStates)); memset(&fNextInfo, 0, sizeof(fNextInfo)); memset(&fCurrentInfo, 0, sizeof(fCurrentInfo)); memset(&fMaxBitrateCtx, 0, sizeof(fMaxBitrateCtx)); memset(fNextHeader,0, H263_REQUIRE_HEADER_SIZE_BYTES);}///////////////////////////////////////////////////////////////////////////////H263plusVideoStreamParser::~H263plusVideoStreamParser(){}///////////////////////////////////////////////////////////////////////////////void H263plusVideoStreamParser::restoreSavedParserState(){ StreamParser::restoreSavedParserState(); fTo = fSavedTo; fNumTruncatedBytes = fSavedNumTruncatedBytes;}///////////////////////////////////////////////////////////////////////////////void H263plusVideoStreamParser::setParseState(){ fSavedTo = fTo; fSavedNumTruncatedBytes = fNumTruncatedBytes; saveParserState(); // Needed for the parsing process in StreamParser}///////////////////////////////////////////////////////////////////////////////void H263plusVideoStreamParser::registerReadInterest( unsigned char* to, unsigned maxSize){ fStartOfFrame = fTo = fSavedTo = to; fLimit = to + maxSize; fMaxSize = maxSize; fNumTruncatedBytes = fSavedNumTruncatedBytes = 0;}///////////////////////////////////////////////////////////////////////////////// parse() , derived from H263Creator of MPEG4IP, h263.cunsigned H263plusVideoStreamParser::parse(u_int64_t & currentDuration){// u_int8_t frameBuffer[H263_BUFFER_SIZE]; // The input buffer // Pointer which tells LoadNextH263Object where to read data to// u_int8_t* pFrameBuffer = fTo + 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;// u_int64_t 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;// u_int64_t totalDuration = 0;// Duration accumulator// u_int64_t avgBitrate; // Average bitrate// u_int64_t totalBytes = 0; // Size accumulator try // The get data routines of the class FramedFilter returns an error when { // the buffer is empty. This occurs at the beginning and at the end of the file. fCurrentInfo = fNextInfo; // Parse 1 frame // For the first time, only the first frame's header is returned. // The second time the full first frame is returned frameSize = parseH263Frame(); currentDuration = 0; if ((frameSize > 0)){ // We were able to acquire a frame from the input. // Parse the returned frame header (if any) if (!ParseShortHeader(fTo, &fNextInfo)) ;// fprintf(stderr,"H263plusVideoStreamParser: Fatal error\n"); trDifference = GetTRDifference(fNextInfo.tr, fCurrentInfo.tr); // calculate the current frame duration currentDuration = CalculateDuration(trDifference); // Accumulate the frame's size and duration for avgBitrate calculation //totalDuration += currentDuration; //totalBytes += frameSize; // If needed, recalculate bitrate information // if (h263Bitrates) //GetMaxBitrate(&fMaxBitrateCtx, frameSize, prevTrDifference); //prevTrDifference = trDifference; } } catch (int /*e*/) {#ifdef DEBUG fprintf(stderr, "H263plusVideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");#endif frameSize=0; } setParseState(); // Needed for the parsing process in StreamParser return frameSize;}///////////////////////////////////////////////////////////////////////////////// parseH263Frame derived from LoadNextH263Object of MPEG4IP // - 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:// ppNextHeader - output parameter that upon return points to the location// of the next frame's head in the buffer.// This pointer shall be NULL for the last frame read.// Returns the total number of bytes read.// Uses FrameFileSource intantiated by constructor.///////////////////////////////////////////////////////////////////////////////int H263plusVideoStreamParser::parseH263Frame( ){ char row = 0; u_int8_t * bufferIndex = fTo; // The buffer end which will allow the loop to leave place for // the additionalBytesNeeded u_int8_t * bufferEnd = fTo + fMaxSize - ADDITIONAL_BYTES_NEEDED - 1; memcpy(fTo, fNextHeader, H263_REQUIRE_HEADER_SIZE_BYTES); bufferIndex += H263_REQUIRE_HEADER_SIZE_BYTES; // The state table and the following loop implements a state machine enabling // us to read bytes from the file until (and inclusing) the requested // start code (00 00 8X) is found // Initialize the states array, if it hasn't been initialized yet... if (!fStates[0][0]) { // One 00 was read fStates[0][0] = 1; // Two sequential 0x00 ware read fStates[1][0] = fStates[2][0] = 2; // A full start code was read fStates[2][128] = fStates[2][129] = fStates[2][130] = fStates[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 { *bufferIndex = get1Byte(); } while ((bufferIndex < bufferEnd) && // We have place in the buffer ((row = fStates[(unsigned char)row][*(bufferIndex++)]) != -1)); // Start code was not found if (row != -1) { fprintf(stderr, "%s: Buffer too small (%u)\n", "h263reader:", bufferEnd - fTo + ADDITIONAL_BYTES_NEEDED); return 0; } // Cool ... now we have a start code // Now we just have to read the additionalBytesNeeded getBytes(bufferIndex, ADDITIONAL_BYTES_NEEDED); memcpy(fNextHeader, bufferIndex - H263_STARTCODE_SIZE_BYTES, H263_REQUIRE_HEADER_SIZE_BYTES); int sz = bufferIndex - fTo - H263_STARTCODE_SIZE_BYTES; if (sz == 5) // first frame memcpy(fTo, fTo+H263_REQUIRE_HEADER_SIZE_BYTES, H263_REQUIRE_HEADER_SIZE_BYTES); return sz;}////////////////////////////////////////////////////////////////////////////////// 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.////////////////////////////////////////////////////////////////////////////////bool H263plusVideoStreamParser::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////////////////////////////////////////////////////////////////////////////////void H263plusVideoStreamParser::GetMaxBitrate( MaxBitrate_CTX *ctx, u_int32_t frameSize,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -