📄 mpeg1or2videostreamframer.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-2004 Live Networks, Inc. All rights reserved.// A filter that breaks up an MPEG 1 or 2 video elementary stream into// frames for: Video_Sequence_Header, GOP_Header, Picture_Header// Implementation#include "MPEG1or2VideoStreamFramer.hh"#include "MPEGVideoStreamParser.hh"#include <string.h>////////// MPEG1or2VideoStreamParser definition //////////// An enum representing the current state of the parser:enum MPEGParseState { PARSING_VIDEO_SEQUENCE_HEADER, PARSING_VIDEO_SEQUENCE_HEADER_SEEN_CODE, PARSING_GOP_HEADER, PARSING_GOP_HEADER_SEEN_CODE, PARSING_PICTURE_HEADER, PARSING_SLICE}; #define VSH_MAX_SIZE 1000class MPEG1or2VideoStreamParser: public MPEGVideoStreamParser {public: MPEG1or2VideoStreamParser(MPEG1or2VideoStreamFramer* usingSource, FramedSource* inputSource, Boolean iFramesOnly, double vshPeriod); virtual ~MPEG1or2VideoStreamParser();private: // redefined virtual functions: virtual void flushInput(); virtual unsigned parse();private: void reset(); MPEG1or2VideoStreamFramer* usingSource() { return (MPEG1or2VideoStreamFramer*)fUsingSource; } void setParseState(MPEGParseState parseState); unsigned parseVideoSequenceHeader(Boolean haveSeenStartCode); unsigned parseGOPHeader(Boolean haveSeenStartCode); unsigned parsePictureHeader(); unsigned parseSlice();private: MPEGParseState fCurrentParseState; unsigned fPicturesSinceLastGOP; // can be used to compute timestamp for a video_sequence_header unsigned short fCurPicTemporalReference; // used to compute slice timestamp unsigned char fCurrentSliceNumber; // set when parsing a slice // A saved copy of the most recently seen 'video_sequence_header', // in case we need to insert it into the stream periodically: unsigned char fSavedVSHBuffer[VSH_MAX_SIZE]; unsigned fSavedVSHSize; double fSavedVSHTimestamp; double fVSHPeriod; Boolean fIFramesOnly, fSkippingCurrentPicture; void saveCurrentVSH(); Boolean needToUseSavedVSH(); unsigned useSavedVSH(); // returns the size of the saved VSH};////////// MPEG1or2VideoStreamFramer implementation //////////MPEG1or2VideoStreamFramer::MPEG1or2VideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource, Boolean iFramesOnly, double vshPeriod, Boolean createParser) : MPEGVideoStreamFramer(env, inputSource) { fParser = createParser ? new MPEG1or2VideoStreamParser(this, inputSource, iFramesOnly, vshPeriod) : NULL;}MPEG1or2VideoStreamFramer::~MPEG1or2VideoStreamFramer() {}MPEG1or2VideoStreamFramer*MPEG1or2VideoStreamFramer::createNew(UsageEnvironment& env, FramedSource* inputSource, Boolean iFramesOnly, double vshPeriod) { // Need to add source type checking here??? ##### return new MPEG1or2VideoStreamFramer(env, inputSource, iFramesOnly, vshPeriod);}double MPEG1or2VideoStreamFramer::getCurrentPTS() const { return fPresentationTime.tv_sec + fPresentationTime.tv_usec/1000000.0;}Boolean MPEG1or2VideoStreamFramer::isMPEG1or2VideoStreamFramer() const { return True;}////////// MPEG1or2VideoStreamParser implementation //////////MPEG1or2VideoStreamParser::MPEG1or2VideoStreamParser(MPEG1or2VideoStreamFramer* usingSource, FramedSource* inputSource, Boolean iFramesOnly, double vshPeriod) : MPEGVideoStreamParser(usingSource, inputSource), fCurrentParseState(PARSING_VIDEO_SEQUENCE_HEADER), fVSHPeriod(vshPeriod), fIFramesOnly(iFramesOnly) { reset();}MPEG1or2VideoStreamParser::~MPEG1or2VideoStreamParser() {}void MPEG1or2VideoStreamParser::setParseState(MPEGParseState parseState) { fCurrentParseState = parseState; MPEGVideoStreamParser::setParseState();}void MPEG1or2VideoStreamParser::reset() { fPicturesSinceLastGOP = 0; fCurPicTemporalReference = 0; fCurrentSliceNumber = 0; fSavedVSHSize = 0; fSkippingCurrentPicture = False;}void MPEG1or2VideoStreamParser::flushInput() { reset(); StreamParser::flushInput(); if (fCurrentParseState != PARSING_VIDEO_SEQUENCE_HEADER) { setParseState(PARSING_GOP_HEADER); // start from the next GOP }}unsigned MPEG1or2VideoStreamParser::parse() { try { switch (fCurrentParseState) { case PARSING_VIDEO_SEQUENCE_HEADER: { return parseVideoSequenceHeader(False); } case PARSING_VIDEO_SEQUENCE_HEADER_SEEN_CODE: { return parseVideoSequenceHeader(True); } case PARSING_GOP_HEADER: { return parseGOPHeader(False); } case PARSING_GOP_HEADER_SEEN_CODE: { return parseGOPHeader(True); } case PARSING_PICTURE_HEADER: { return parsePictureHeader(); } case PARSING_SLICE: { return parseSlice(); } default: { return 0; // shouldn't happen } } } catch (int /*e*/) {#ifdef DEBUG fprintf(stderr, "MPEG1or2VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");#endif return 0; // the parsing got interrupted }}void MPEG1or2VideoStreamParser::saveCurrentVSH() { unsigned frameSize = curFrameSize(); if (frameSize > sizeof fSavedVSHBuffer) return; // too big to save memmove(fSavedVSHBuffer, fStartOfFrame, frameSize); fSavedVSHSize = frameSize; fSavedVSHTimestamp = usingSource()->getCurrentPTS();}Boolean MPEG1or2VideoStreamParser::needToUseSavedVSH() { return usingSource()->getCurrentPTS() > fSavedVSHTimestamp+fVSHPeriod && fSavedVSHSize > 0;}unsigned MPEG1or2VideoStreamParser::useSavedVSH() { unsigned bytesToUse = fSavedVSHSize; unsigned maxBytesToUse = fLimit - fStartOfFrame; if (bytesToUse > maxBytesToUse) bytesToUse = maxBytesToUse; memmove(fStartOfFrame, fSavedVSHBuffer, bytesToUse); // Also reset the saved timestamp: fSavedVSHTimestamp = usingSource()->getCurrentPTS();#ifdef DEBUG fprintf(stderr, "used saved video_sequence_header (%d bytes)\n", bytesToUse);#endif return bytesToUse;}#define VIDEO_SEQUENCE_HEADER_START_CODE 0x000001B3#define GROUP_START_CODE 0x000001B8#define PICTURE_START_CODE 0x00000100#define SEQUENCE_END_CODE 0x000001B7static double const frameRateFromCode[] = { 0.0, // forbidden 24000/1001.0, // approx 23.976 24.0, 25.0, 30000/1001.0, // approx 29.97 30.0, 50.0, 60000/1001.0, // approx 59.94 60.0, 0.0, // reserved 0.0, // reserved 0.0, // reserved 0.0, // reserved 0.0, // reserved 0.0, // reserved 0.0 // reserved
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -