📄 mpeg.c
字号:
*framePP = frameP;}static voidcomputeFrameRange(unsigned int const frameStart, unsigned int const frameEnd, enum frameContext const context, struct inputSource * const inputSourceP, unsigned int * const firstFrameP, unsigned int * const lastFrameP) { switch (context) { case CONTEXT_GOP: *firstFrameP = frameStart; *lastFrameP = frameEnd; break; case CONTEXT_JUSTFRAMES: { /* if first frame is P or B, need to read in P or I frame before it */ if (FType_Type(frameStart) != 'i') { /* can't find the previous frame interactively */ if (inputSourceP->stdinUsed) pm_error("Cannot encode frames from Standard Input " "when first frame is not an I-frame."); *firstFrameP = FType_PastRef(frameStart); } else *firstFrameP = frameStart; /* if last frame is B, need to read in P or I frame after it */ if ((FType_Type(frameEnd) == 'b') && (frameEnd != inputSourceP->numInputFiles-1)) { /* can't find the next reference frame interactively */ if (inputSourceP->stdinUsed) pm_error("Cannot encode frames from Standard Input " "when last frame is a B-frame."); *lastFrameP = FType_FutureRef(frameEnd); } else *lastFrameP = frameEnd; } break; case CONTEXT_WHOLESTREAM: *firstFrameP = frameStart; *lastFrameP = frameEnd; }}static voidgetFrame(MpegFrame ** const framePP, struct inputSource * const inputSourceP, unsigned int const frameNumber, char const frameType, unsigned int const realStart, unsigned int const realEnd, int const referenceFrame, boolean const childProcess, boolean const remoteIo, boolean const separateConversion, const char * const slaveConversion, const char * const inputConversion, unsigned int * const framesReadP, int * const ioTimeP) { time_t ioTimeStart, ioTimeEnd; MpegFrame * frameP; time(&ioTimeStart); frameP = Frame_New(frameNumber, frameType); if ((referenceFrame == DECODED_FRAME) && ((frameNumber < realStart) || (frameNumber > realEnd)) ) { WaitForDecodedFrame(frameNumber); if (remoteIo) GetRemoteDecodedRefFrame(frameP, frameNumber); else ReadDecodedRefFrame(frameP, frameNumber); } else ReadNthFrame(inputSourceP, frameNumber, remoteIO, childProcess, separateConversion, slaveConversion, inputConversion, frameP); ++(*framesReadP); time(&ioTimeEnd); *ioTimeP += (ioTimeEnd - ioTimeStart); *framePP = frameP;}static voidhandleBitRate(unsigned int const realEnd, unsigned int const numBits, boolean const childProcess, boolean const showBitRatePerFrame) { extern void PrintItoIBitRate (int numBits, int frameNum); if (FType_Type(realEnd) != 'i') PrintItoIBitRate(numBits, realEnd+1); if ((!childProcess) && showBitRatePerFrame) CloseBitRateFile();}voidGenMPEGStream(struct inputSource * const inputSourceP, enum frameContext const context, unsigned int const frameStart, unsigned int const frameEnd, int32 const qtable[], int32 const niqtable[], bool const childProcess, FILE * const ofp, const char * const outputFileName, bool const wantVbvUnderflowWarning, bool const wantVbvOverflowWarning, unsigned int * const inputFrameBitsP, unsigned int * const totalBitsP) {/*---------------------------------------------------------------------------- Encode a bunch of frames into an MPEG sequence stream or a part thereof. 'context' tells what in addition to the frames themselves must go into the stream: CONTEXT_JUSTFRAMES: Nothing but the indicated frames CONTEXT_GOP: GOP header/trailer stuff to make a single GOP that contains the indicated frames CONTEXT_WHOLESTREAM: A whole stream consisting of the indicated frames -- a sequence of whole GOPS, with stream header/trailer stuff as well.-----------------------------------------------------------------------------*/ BitBucket *bb; unsigned int frameNumber; char frameType; boolean firstFrameDone; int numBits; unsigned int firstFrame, lastFrame; /* Frame numbers of the first and last frames we look at. This could be more than the the frames we actually encode because we may need context (i.e. to encode a B frame, we need the subsequent I or P frame). */ unsigned int framesRead; /* Number of frames we have read; for statistical purposes */ MpegFrame * pastRefFrameP; /* The frame that will be the past reference frame for the next B or P frame that we put into the stream */ if (frameEnd + 1 > inputSourceP->numInputFiles) pm_error("Last frame (number %u) is beyond the end of the stream " "(%u frames)", frameEnd, inputSourceP->numInputFiles); if (context == CONTEXT_WHOLESTREAM && (!inputSourceP->stdinUsed) && (FType_Type(inputSourceP->numInputFiles-1) == 'b')) pm_message("WARNING: " "One or more B-frames at end will not be encoded. " "See FORCE_ENCODE_LAST_FRAME parameter file statement."); time(&timeStart); framesRead = 0; ResetIFrameStats(); ResetPFrameStats(); ResetBFrameStats(); Fsize_Reset(); framesOutput = 0; if (childProcess && separateConversion) SetFileType(slaveConversion); else SetFileType(inputConversion); realStart = frameStart; realEnd = frameEnd; computeFrameRange(frameStart, frameEnd, context, inputSourceP, &firstFrame, &lastFrame); if (context == CONTEXT_GOP && FType_Type(frameStart) == 'b') getPreviousFrame(frameStart, referenceFrame, inputSourceP, childProcess, slaveConversion, inputConversion, &pastRefFrameP, &framesRead, &IOtime); else pastRefFrameP = NULL; countFrames(firstFrame, lastFrame, inputSourceP->stdinUsed, &numI, &numP, &numB, &timeMask, &frameCountsUnknown); if (showBitRatePerFrame) OpenBitRateFile(); /* May modify showBitRatePerFrame */ if (context == CONTEXT_WHOLESTREAM) bb = Bitio_New(ofp); else bb = NULL; initTCTime(firstFrame); totalFramesSent = firstFrame; currentGOP = gopSize; /* so first I-frame generates GOP Header */ initializeRateControl(wantVbvUnderflowWarning, wantVbvOverflowWarning); firstFrameDone = FALSE; for (frameNumber = firstFrame; frameNumber <= lastFrame; ++frameNumber) { /* break out of the near-infinite loop if input from stdin is done */ if (inputSourceP->stdinUsed) { int eofcheck_; eofcheck_ = fgetc(stdin); if (eofcheck_ == EOF) break; else ungetc(eofcheck_, stdin); } frameType = FType_Type(frameNumber); if (frameType == 'b') { /* We'll process this non-reference frame later. If reading from stdin, we read it now and save it. Otherwise, we can just read it later. */ if (inputSourceP->stdinUsed) readAndSaveFrame(inputSourceP, frameNumber, frameType, inputConversion, pastRefFrameP, &framesRead, &IOtime); } else { MpegFrame * frameP; getFrame(&frameP, inputSourceP, frameNumber, frameType, realStart, realEnd, referenceFrame, childProcess, remoteIO, separateConversion, slaveConversion, inputConversion, &framesRead, &IOtime); if (!firstFrameDone) { doFirstFrameStuff(context, userDataFileName, bb, Fsize_x, Fsize_y, aspectRatio, frameRate, qtable, niqtable, inputFrameBitsP); firstFrameDone = TRUE; } processRefFrame(frameP, bb, lastFrame, frameStart, frameEnd, pastRefFrameP, childProcess, outputFileName, &framesRead, &framesOutput); if (pastRefFrameP) { processBFrames(pastRefFrameP, frameP, realStart, realEnd, inputSourceP, remoteIO, childProcess, &IOtime, bb, outputFileName, &framesRead, &framesOutput, ¤tGOP); } if (pastRefFrameP != NULL) Frame_Free(pastRefFrameP); pastRefFrameP = frameP; } } if (pastRefFrameP != NULL) Frame_Free(pastRefFrameP); /* SEQUENCE END CODE */ if (context == CONTEXT_WHOLESTREAM) Mhead_GenSequenceEnder(bb); if (context == CONTEXT_WHOLESTREAM) numBits = bb->cumulativeBits; else { /* What should the correct value be? Most likely 1. "numBits" is used below, so we need to make sure it's properly initialized to somthing (anything). */ numBits = 1; } if (context != CONTEXT_JUSTFRAMES) { Bitio_Flush(bb); bb = NULL; fclose(ofp); } handleBitRate(realEnd, numBits, childProcess, showBitRatePerFrame); *totalBitsP = numBits;}/*===========================================================================* * * SetStatFileName * * set the statistics file name * * RETURNS: nothing * * SIDE EFFECTS: statFileName * *===========================================================================*/voidSetStatFileName(const char * const fileName) { strcpy(statFileName, fileName);}/*===========================================================================* * * SetGOPSize * * set the GOP size (frames per GOP) * * RETURNS: nothing * * SIDE EFFECTS: gopSize * *===========================================================================*/voidSetGOPSize(size) int size;{ gopSize = size;}/*===========================================================================* * * PrintStartStats * * print out the starting statistics (stuff from the param file) * * RETURNS: nothing * * SIDE EFFECTS: none * *===========================================================================*/voidPrintStartStats(time_t const startTime, bool const specificFrames, unsigned int const firstFrame, unsigned int const lastFrame, struct inputSource * const inputSourceP) { FILE *fpointer; int i; if (statFileName[0] == '\0') { statFile = NULL; } else { statFile = fopen(statFileName, "a"); /* open for appending */ if (statFile == NULL) { fprintf(stderr, "ERROR: Could not open stat file: %s\n", statFileName); fprintf(stderr, " Sending statistics to stdout only.\n"); fprintf(stderr, "\n\n"); } else if (! realQuiet) { fprintf(stdout, "Appending statistics to file: %s\n", statFileName); fprintf(stdout, "\n\n"); } } for (i = 0; i < 2; ++i) { if ( ( i == 0 ) && (! realQuiet) ) { fpointer = stdout; } else if ( statFile != NULL ) { fpointer = statFile; } else { continue; } fprintf(fpointer, "MPEG ENCODER STATS (%s)\n",VERSION); fprintf(fpointer, "------------------------\n"); fprintf(fpointer, "TIME STARTED: %s", ctime(&startTime)); if (getenv("HOST") != NULL) fprintf(fpointer, "MACHINE: %s\n", getenv("HOST")); else fprintf(fpointer, "MACHINE: unknown\n"); if (inputSourceP->stdinUsed) fprintf(fpointer, "INPUT: stdin\n"); else { const char * inputFileName; fprintf(fpointer, "INPUT FROM FILES:\n"); GetNthInputFileName(inputSourceP, 0, &inputFileName); fprintf(fpointer, "FIRST FILE: %s/%s\n", currentPath, inputFileName); strfree(inputFileName); GetNthInputFileName(inputSourceP, inputSourceP->numInputFiles-1, &inputFileName); fprintf(fpointer, "LAST FILE: %s/%s\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -