📄 mpeg.c
字号:
bbP = Bitio_New(NULL); else { const char * fileName; asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber); bbP = Bitio_New_Filename(fileName); strfree(fileName); } return bbP;}static voidgetBFrame(int const frameNum, struct inputSource * const inputSourceP, MpegFrame * const pastRefFrameP, boolean const childProcess, boolean const remoteIO, MpegFrame ** const bFramePP, int * const IOtimeP, unsigned int * const framesReadP) {/*---------------------------------------------------------------------------- Get Frame 'frameNum', which is a B frame related to previous reference frame 'pastRefFrameP'. Return it as *bFramePP. We have various ways of getting the frame, corresponding to the multitude of modes in which Ppmtompeg works.-----------------------------------------------------------------------------*/ if (!inputSourceP->stdinUsed) { time_t tempTimeStart, tempTimeEnd; MpegFrame * bFrameP; bFrameP = Frame_New(frameNum, 'b'); time(&tempTimeStart); ReadNthFrame(inputSourceP, frameNum, remoteIO, childProcess, separateConversion, slaveConversion, inputConversion, bFrameP); time(&tempTimeEnd); *IOtimeP += (tempTimeEnd-tempTimeStart); ++(*framesReadP); *bFramePP = bFrameP; } else { /* As the frame input is serial, we can't read the B frame now. Rather, Caller has already read it and chained it to the previous reference frame. So we get that copy now. */ *bFramePP = pastRefFrameP->next; pastRefFrameP->next = (*bFramePP)->next; /* unlink from list */ }}static voidprocessBFrames(MpegFrame * const pastRefFrameP, MpegFrame * const futureRefFrameP, int const realStart, int const realEnd, struct inputSource * const inputSourceP, boolean const remoteIo, boolean const childProcess, int * const IOtimeP, BitBucket * const wholeStreamBbP, const char * const outputFileName, unsigned int * const framesReadP, unsigned int * const framesOutputP, int * const currentGopP) {/*---------------------------------------------------------------------------- Process the B frames that go between 'pastRefFrameP' and 'futureRefFrame' in the movie (but go after 'futureRefFrameP' in the MPEG stream, so reader doesn't have to read ahead). Remember that a B frame is one which is described by data in the MPEG stream that describes the frame with respect to a frame somewhere before it, and a frame somewhere after it (i.e. reference frames). But do only those B frames whose frame numbers are within the range 'realStart' through 'realEnd'.-----------------------------------------------------------------------------*/ boolean const separateFiles = (wholeStreamBbP == NULL); unsigned int const firstBFrameNum = pastRefFrameP->id + 1; int frameNum; assert(pastRefFrameP != NULL); assert(futureRefFrameP != NULL); for (frameNum = MAX(realStart, firstBFrameNum); frameNum < MIN(realEnd, futureRefFrameP->id); ++frameNum) { MpegFrame * bFrame; BitBucket * bbP; getBFrame(frameNum, inputSourceP, pastRefFrameP, childProcess, remoteIO, &bFrame, IOtimeP, framesReadP); if (separateFiles) bbP = bitioNew(outputFileName, bFrame->id, remoteIO); else bbP = wholeStreamBbP; GenBFrame(bbP, bFrame, pastRefFrameP, futureRefFrameP); ++(*framesOutputP); if (separateFiles) { if (remoteIO) SendRemoteFrame(bFrame->id, bbP); else { Bitio_Flush(bbP); Bitio_Close(bbP); } } /* free this B frame right away */ Frame_Free(bFrame); numB--; timeMask &= 0x3; ShowRemainingTime(childProcess); ++(*currentGopP); IncrementTCTime(); }}static voidprocessRefFrame(MpegFrame * const frameP, BitBucket * const bb_arg, int const lastFrame, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP, boolean const childProcess, const char * const outputFileName, unsigned int * const framesReadP, unsigned int * const framesOutputP) {/*---------------------------------------------------------------------------- Process an I or P frame. Encode and output it. But only if its frame number is within the range 'realStart' through 'realEnd'.-----------------------------------------------------------------------------*/ if (frameP->id >= realStart && frameP->id <= realEnd) { boolean separateFiles; BitBucket * bb; separateFiles = (bb_arg == NULL); if ( separateFiles ) bb = bitioNew(outputFileName, frameP->id, remoteIO); else bb = bb_arg; /* first, output this reference frame */ switch (frameP->type) { case TYPE_IFRAME: outputIFrame(frameP, bb, realStart, realEnd, pastRefFrameP, separateFiles); break; case TYPE_PFRAME: outputPFrame(frameP, bb, realStart, realEnd, pastRefFrameP); ShowRemainingTime(childProcess); break; default: pm_error("INTERNAL ERROR: non-reference frame passed to " "ProcessRefFrame()"); } ++(*framesOutputP); finishFrameOutput(frameP, bb, separateFiles, referenceFrame, childProcess, remoteIO); }}static voidcountFrames(unsigned int const firstFrame, unsigned int const lastFrame, boolean const stdinUsed, int * const numIP, int * const numPP, int * const numBP, int * const timeMaskP, boolean * const frameCountsUnknownP) {/*---------------------------------------------------------------------------- Count number of I, P, and B frames-----------------------------------------------------------------------------*/ unsigned int numI, numP, numB; unsigned int timeMask; numI = 0; numP = 0; numB = 0; timeMask = 0; if (stdinUsed) { numI = numP = numB = MAXINT/4; *frameCountsUnknownP = TRUE; } else { unsigned int i; for (i = firstFrame; i <= lastFrame; ++i) { char const frameType = FType_Type(i); switch(frameType) { case 'i': numI++; timeMask |= 0x1; break; case 'p': numP++; timeMask |= 0x2; break; case 'b': numB++; timeMask |= 0x4; break; } } *frameCountsUnknownP = FALSE; } *numIP = numI; *numPP = numP; *numBP = numB; *timeMaskP = timeMask; *frameCountsUnknownP = frameCountsUnknown;}static voidreadAndSaveFrame(struct inputSource * const inputSourceP, unsigned int const frameNumber, char const frameType, const char * const inputConversion, MpegFrame * const pastRefFrameP, unsigned int * const framesReadP, int * const ioTimeP) {/*---------------------------------------------------------------------------- Read the next frame from Standard Input and add it to the linked list at *pastRefFrameP. Assume it is Frame Number 'frameNumber' and is of type 'frameType'. Add the time it took to read it, in seconds, to *iotimeP.-----------------------------------------------------------------------------*/ /* This really should be part of ReadNthFrame. The frame should be chained to the input object, not the past reference frame. */ MpegFrame * p; MpegFrame * frameP; time_t ioTimeStart, ioTimeEnd; time(&ioTimeStart); frameP = Frame_New(frameNumber, frameType); ReadFrame(frameP, inputSourceP, frameNumber, inputConversion); ++(*framesReadP); time(&ioTimeEnd); *ioTimeP += (ioTimeEnd - ioTimeStart); /* Add the B frame to the end of the queue of B-frames for later encoding. */ assert(pastRefFrameP != NULL); p = pastRefFrameP; while (p->next != NULL) p = p->next; p->next = frameP;}static voiddoFirstFrameStuff(enum frameContext const context, const char * const userDataFileName, BitBucket * const bb, int const fsize_x, int const fsize_y, int const aspectRatio, int const frameRate, int32 const qtable[], int32 const niqtable[], unsigned int * const inputFrameBitsP) {/*---------------------------------------------------------------------------- Do stuff we have to do after reading the first frame in a sequence of frames requested of GenMPEGStream().-----------------------------------------------------------------------------*/ *inputFrameBitsP = 24*Fsize_x*Fsize_y; SetBlocksPerSlice(); if (context == CONTEXT_WHOLESTREAM) { int32 const bitstreamMode = getRateMode(); char * userData; unsigned int userDataSize; assert(bb != NULL); DBG_PRINT(("Generating sequence header\n")); if (bitstreamMode == FIXED_RATE) { bit_rate = getBitRate(); buf_size = getBufferSize(); } else { bit_rate = -1; buf_size = -1; } if (strlen(userDataFileName) != 0) { struct stat statbuf; FILE *fp; stat(userDataFileName,&statbuf); userDataSize = statbuf.st_size; userData = malloc(userDataSize); fp = fopen(userDataFileName,"rb"); if (fp == NULL) { pm_message("Could not open userdata file '%s'.", userDataFileName); userData = NULL; userDataSize = 0; } else { size_t bytesRead; bytesRead = fread(userData,1,userDataSize,fp); if (bytesRead != userDataSize) { pm_message("Could not read %d bytes from " "userdata file '%s'.", userDataSize,userDataFileName); userData = NULL; userDataSize = 0; } } } else { /* Put in our UserData Header */ const char * userDataString; time_t now; time(&now); asprintfN(&userDataString,"MPEG stream encoded by UCB Encoder " "(mpeg_encode) v%s on %s.", VERSION, ctime(&now)); userData = strdup(userDataString); userDataSize = strlen(userData); strfree(userDataString); } Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio, /* pict_rate */ frameRate, /* bit_rate */ bit_rate, /* buf_size */ buf_size, /*c_param_flag */ 1, /* iq_matrix */ qtable, /* niq_matrix */ niqtable, /* ext_data */ NULL, /* ext_data_size */ 0, /* user_data */ (uint8*) userData, /* user_data_size */ userDataSize); }}static voidgetPreviousFrame(unsigned int const frameStart, int const referenceFrame, struct inputSource * const inputSourceP, boolean const childProcess, const char * const slaveConversion, const char * const inputConversion, MpegFrame ** const framePP, unsigned int * const framesReadP, int * const ioTimeP) { MpegFrame * frameP; time_t ioTimeStart, ioTimeEnd; /* can't find the previous frame interactively */ if (inputSourceP->stdinUsed) pm_error("Cannot encode GOP from stdin when " "first frame is a B-frame."); if (frameStart < 1) pm_error("Cannot encode GOP when first frame is a B-frame " "and is not preceded by anything."); /* need to load in previous frame; call it an I frame */ frameP = Frame_New(frameStart-1, 'i'); time(&ioTimeStart); if ((referenceFrame == DECODED_FRAME) && childProcess) { WaitForDecodedFrame(frameStart); if (remoteIO) GetRemoteDecodedRefFrame(frameP, frameStart - 1); else ReadDecodedRefFrame(frameP, frameStart - 1); } else ReadNthFrame(inputSourceP, frameStart - 1, remoteIO, childProcess, separateConversion, slaveConversion, inputConversion, frameP); ++(*framesReadP); time(&ioTimeEnd); *ioTimeP += (ioTimeEnd-ioTimeStart);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -