📄 mpeg.c
字号:
/*===========================================================================* * mpeg.c * * Procedures to generate the MPEG sequence *===========================================================================*//* * Copyright (c) 1995 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *//*==============* * HEADER FILES * *==============*/#include "all.h"#include <time.h>#include <errno.h>#include <unistd.h>#include <assert.h>#ifdef MIPS#include <sys/types.h>#endif#include <sys/stat.h>#include "ppm.h"#include "nstring.h"#include "mtypes.h"#include "frames.h"#include "motion_search.h"#include "prototypes.h"#include "parallel.h"#include "param.h"#include "readframe.h"#include "fsize.h"#include "mheaders.h"#include "rate.h"#include "input.h"#include "frametype.h"#include "mpeg.h"/*===========* * VERSION * *===========*/#define VERSION "1.5b"/*===========* * CONSTANTS * *===========*/#define FPS_30 0x5 /* from MPEG standard sect. 2.4.3.2 */#define ASPECT_1 0x1 /* aspect ratio, from MPEG standard sect. 2.4.3.2 *//*==================* * STATIC VARIABLES * *==================*/static unsigned int framesOutput;static int realStart, realEnd;static int currentGOP;static int timeMask;static int numI, numP, numB;static boolean frameCountsUnknown;/*==================* * GLOBAL VARIABLES * *==================*//* important -- don't initialize anything here *//* must be re-initted anyway in GenMPEGStream */extern int IOtime;extern boolean resizeFrame;extern int outputWidth, outputHeight;int gopSize = 100; /* default */int32 tc_hrs, tc_min, tc_sec, tc_pict, tc_extra;int totalFramesSent;int yuvWidth, yuvHeight;int realWidth, realHeight;char currentPath[MAXPATHLEN];char statFileName[256];char bitRateFileName[256];time_t timeStart, timeEnd;FILE *statFile;FILE *bitRateFile = NULL;char *framePattern;int framePatternLen;int referenceFrame;int frameRate = FPS_30;int frameRateRounded = 30;boolean frameRateInteger = TRUE;int aspectRatio = ASPECT_1;extern char userDataFileName[];extern int mult_seq_headers;int32 bit_rate, buf_size;/*===============================* * INTERNAL PROCEDURE prototypes * *===============================*/static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText));static void OpenBitRateFile _ANSI_ARGS_((void));static void CloseBitRateFile _ANSI_ARGS_((void));static voidShowRemainingTime(boolean const childProcess) {/*---------------------------------------------------------------------------- Print out an estimate of the time left to encode-----------------------------------------------------------------------------*/ if (childProcess) { /* nothing */; } else if ( numI + numP + numB == 0 ) { /* no time left */ } else if ( timeMask != 0 ) { /* haven't encoded all types yet */ } else { static int lastTime = 0; float total; time_t nowTime; float secondsPerFrame; time(&nowTime); secondsPerFrame = (nowTime-timeStart)/(float)framesOutput; total = secondsPerFrame*(float)(numI+numP+numB); if ((quietTime >= 0) && (!realQuiet) && (!frameCountsUnknown) && ((lastTime < (int)total) || ((lastTime-(int)total) >= quietTime) || (lastTime == 0) || (quietTime == 0))) { if (total > 270.0) pm_message("ESTIMATED TIME OF COMPLETION: %d minutes", ((int)total+30)/60); else pm_message("ESTIMATED TIME OF COMPLETION: %d seconds", (int)total); } lastTime = (int)total; }}static voidinitTCTime(unsigned int const firstFrameNumber) { unsigned int frameNumber; tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0; for (frameNumber = 0; frameNumber < firstFrameNumber; ++frameNumber) IncrementTCTime();}/*===========================================================================* * * IncrementTCTime * * increment the tc time by one second (and update min, hrs if necessary) * also increments totalFramesSent * * RETURNS: nothing * * SIDE EFFECTS: totalFramesSent, tc_pict, tc_sec, tc_min, tc_hrs, tc_extra * *===========================================================================*/voidIncrementTCTime() { /* if fps = an integer, then tc_extra = 0 and is ignored otherwise, it is the number of extra 1/1001 frames we've passed by so far; for example, if fps = 24000/1001, then 24 frames = 24024/24000 seconds = 1 second + 24/24000 seconds = 1 + 1/1000 seconds; similary, if fps = 30000/1001, then 30 frames = 30030/30000 = 1 + 1/1000 seconds and if fps = 60000/1001, then 60 frames = 1 + 1/1000 seconds if fps = 24000/1001, then 1/1000 seconds = 24/1001 frames if fps = 30000/1001, then 1/1000 seconds = 30/1001 frames if fps = 60000/1001, then 1/1000 seconds = 60/1001 frames */ totalFramesSent++; tc_pict++; if ( tc_pict >= frameRateRounded ) { tc_pict = 0; tc_sec++; if ( tc_sec == 60 ) { tc_sec = 0; tc_min++; if ( tc_min == 60 ) { tc_min = 0; tc_hrs++; } } if ( ! frameRateInteger ) { tc_extra += frameRateRounded; if ( tc_extra >= 1001 ) { /* a frame's worth */ tc_pict++; tc_extra -= 1001; } } }}static voidinitializeRateControl(bool const wantUnderflowWarning, bool const wantOverflowWarning) {/*---------------------------------------------------------------------------- Initialize rate control-----------------------------------------------------------------------------*/ int32 const bitstreamMode = getRateMode(); if (bitstreamMode == FIXED_RATE) { initRateControl(wantUnderflowWarning, wantOverflowWarning); /* SetFrameRate(); */ }} /*===========================================================================* * * SetReferenceFrameType * * set the reference frame type to be original or decoded * * RETURNS: nothing * * SIDE EFFECTS: referenceFrame * *===========================================================================*/voidSetReferenceFrameType(const char * const type) { if (strcmp(type, "ORIGINAL") == 0) referenceFrame = ORIGINAL_FRAME; else if ( strcmp(type, "DECODED") == 0 ) referenceFrame = DECODED_FRAME; else pm_error("INTERNAL ERROR: Illegal reference frame type: '%s'", type);}voidSetBitRateFileName(fileName) char *fileName;{ strcpy(bitRateFileName, fileName);}static voidfinishFrameOutput(MpegFrame * const frameP, BitBucket * const bbP, boolean const separateFiles, int const referenceFrame, boolean const childProcess, boolean const remoteIO) { if ((referenceFrame == DECODED_FRAME) && childProcess && NonLocalRefFrame(frameP->id)) { if (remoteIO) SendDecodedFrame(frameP); else WriteDecodedFrame(frameP); NotifyDecodeServerReady(frameP->id); } if (separateFiles) { if (remoteIO) SendRemoteFrame(frameP->id, bbP); else { Bitio_Flush(bbP); Bitio_Close(bbP); } }} static voidoutputIFrame(MpegFrame * const frameP, BitBucket * const bb, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP, boolean const separateFiles) { /* only start a new GOP with I */ /* don't start GOP if only doing frames */ if ((!separateFiles) && (currentGOP >= gopSize)) { boolean const closed = (totalFramesSent == frameP->id || pastRefFrameP == NULL); static int num_gop = 0; /* first, check to see if closed GOP */ /* new GOP */ if (num_gop != 0 && mult_seq_headers && num_gop % mult_seq_headers == 0) { if (!realQuiet) { fprintf(stdout, "Creating new Sequence before GOP %d\n", num_gop); fflush(stdout); } 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 */ customQtable, /* niq_matrix */ customNIQtable, /* ext_data */ NULL, /* ext_data_size */ 0, /* user_data */ NULL, /* user_data_size */ 0); } if (!realQuiet) pm_message("Creating new GOP (closed = %s) before frame %d\n", closed ? "YES" : "NO", frameP->id); ++num_gop; Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, tc_hrs, tc_min, tc_sec, tc_pict, closed, /* broken_link */ 0, /* ext_data */ NULL, /* ext_data_size */ 0, /* user_data */ NULL, /* user_data_size */ 0); currentGOP -= gopSize; if (pastRefFrameP == NULL) SetGOPStartTime(0); else SetGOPStartTime(pastRefFrameP->id+1); } if ((frameP->id >= realStart) && (frameP->id <= realEnd)) GenIFrame(bb, frameP); numI--; timeMask &= 0x6; currentGOP++; IncrementTCTime();}static voidoutputPFrame(MpegFrame * const frameP, BitBucket * const bbP, int const realStart, int const realEnd, MpegFrame * const pastRefFrameP) { if ((frameP->id >= realStart) && (frameP->id <= realEnd)) GenPFrame(bbP, frameP, pastRefFrameP); numP--; timeMask &= 0x5; currentGOP++; IncrementTCTime();}static BitBucket *bitioNew(const char * const outputFileName, unsigned int const frameNumber, boolean const remoteIO) { BitBucket * bbP; if (remoteIO)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -