📄 mpeg2video.cc
字号:
/* File: mpeg2video.cc By: Alex Theo de Jong Created: February 1996 Description: Implementation of the MPEG 2 Video class*/#define RELEASE "1.2, November 1996"#ifdef __GNUG__#pragma implementation#endif#include "athread.hh"#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <String.h>#include <fstream.h>#ifdef USE_OPENPTC#include <ptc/ptc.h>#endif#include "error.hh"#include "debug.hh"#include "util.hh"#include "sync.hh"#include "mpeg2const.hh"#include "mpeg2buff.hh"#include "videoconst.hh"#include "display.hh"#include "idct.hh"#include "vstream.hh"#include "layerdata.hh"#define GLOBAL#include "global.hh"#include "mpeg2video.hh"/* * * Mpeg2Video * */int error=0;Mpeg2Video::Mpeg2Video(Mpeg2Buffer* input_buffer, Synchronization* s, int c, char** v) : argc(c), terminate(0), terminated(0), blockreadsize(0), framerate(0), skip_state(0), skip_count(0), skipped_frames(0) { if (argc) argv=v; else argv=0; if (options()){ // parse options // create layer data (including display) ::ld=new LayerData(displaytitle.chars(), s); // set or create video data buffer if (input_buffer) ld->input=new VideoStream(input_buffer, s); else ld->input=0; // start player thread if ((error=athr_create((void*(*)(void*))Mpeg2Video::player, this, &thread_id))<0){ error("could not create video player"); athr_exit(0); } /* Seem to slow things donw! */ sched_param param; int policy; if (athr_getschedparam(thread_id, &policy , ¶m)<0){ error("could not get thread priority"); }#ifdef LINUX param.sched_priority+=1;// policy = SCHED_RR; TRACER("VIDEOPRIORITY=" << param.sched_priority << "(" << param.sched_priority-2 << ")");#else param.prio+=2; TRACER("VIDEOPRIORITY=" << param.prio << "(" << param.prio-2 << ")");#endif if (athr_setschedparam(thread_id, policy, ¶m)<0){ error("could not set thread priority"); } }}Mpeg2Video::~Mpeg2Video(){ terminate=1; if (!terminated){ TRACER("waiting for video thread to terminate ... "); athr_join(thread_id); }#if 0 delete ::ld; delete llframe1[0]; delete lltmp; for (int i=0; i<3; i++){ delete auxframe[i]; delete refframe[i]; delete oldrefframe[i];// delete llframe1[0];// delete lltmp; }#endif TRACER("video thread terminated");}void* Mpeg2Video::player(Mpeg2Video* base){ base->terminate=0; base->terminated=0; base->play(); base->terminated=1; athr_exit(0); return 0;}const int NBR_FRAMES = 100;Mpeg2Video* mv=0;int Mpeg2Video::play(){ TRACER("int Mpeg2Video::play()"); timeval tstart; // Time start timeval sstart; // Sequence of NBR_FRAMES start timeval fstart, fstop; // Frame start and stop//verbose=2; framenum=0; skip_state=0; skip_count=0; skipped_frames=0; i_c=p_c=b_c=d_c=0; if (!ld->input) ld->input=new VideoStream(filename.chars()); // read from file if (blockreadsize) ld->input->set_read_block_size(blockreadsize); ::vs=ld->input; while (!terminate && ld->getheader() && (!ld->sync || !ld->sync->done(1))){ if (!framenum){ initdecoder(); gettimeofday(&tstart, 0); gettimeofday(&sstart, 0); gettimeofday(&fstart, 0); } playedlastframe=0; // Allow B-frames to be skipped if in "skip_state" switch(pict_type){ case B_TYPE : b_c++; if (skip_state<=0) ld->getpicture(framenum); else skipped_frames++; break; case P_TYPE : p_c++; ld->getpicture(framenum); break; case I_TYPE : i_c++; ld->getpicture(framenum); break; case D_TYPE : d_c++; if (!skip_state) ld->getpicture(framenum); else skipped_frames++; break; default : error("unknown frame in video stream"); } framenum++; // cruzial to have this here!! athr_yield(); if (!secondfield){ if (ld->sync && !playedlastframe) if (ld->sync->skip(1)<0) break; // skip PTS, <0 end of file if (framerate!=0){ gettimeofday(&fstop, 0); doframerate(fstart, fstop); gettimeofday(&fstart, 0); } } if (!quiet && framenum>1 && (framenum % NBR_FRAMES)==0){ showframerate(sstart); gettimeofday(&sstart, 0); } } if (framenum!=0) ld->putlast(); // put last frame if (!quiet && framenum) showframerateend(tstart); return 0;}void Mpeg2Video::doframerate(timeval& fstart, timeval& fstop){ int time_real_usec= (fstop.tv_sec-fstart.tv_sec)*1000000+(fstop.tv_usec-fstart.tv_usec); if (time_real_usec > time_interval_usec){ if (++skip_count>0) skip_state=1; // Running behind return; } else { // Running ahead if (--skip_count<-2){ skip_state=0;// timer.waitcond(time_interval_usec - time_real_usec); timer.wait(time_interval_usec - time_real_usec); } return; }}int Mpeg2Video::showframerate(timeval& sstart){ // show frame rate every NBR_FRAMES frames static char txt[100]; timeval tstop; gettimeofday(&tstop,(struct timezone *)NULL); unsigned int runtime=1000*(tstop.tv_sec-sstart.tv_sec)+(tstop.tv_usec-sstart.tv_usec)/1000; sprintf(txt, " %d.%02d fps ", (1000*NBR_FRAMES/runtime), ((100000*NBR_FRAMES/runtime)%100)); msg(txt); return 1;}int Mpeg2Video::showframerateend(timeval& tstart){ static char txt[100]; timeval tstop; gettimeofday(&tstop,(struct timezone *)NULL); int runtime = 1000*(tstop.tv_sec-tstart.tv_sec)+(tstop.tv_usec-tstart.tv_usec)/1000;/* sprintf(errortext, "\n%d.%02d seconds, %d frames, %d.%02d fps (%d B frames skipped)", runtime/100, runtime%100, framenum, ((10000*framenum+runtime/2)/runtime)/100, ((10000*framenum+runtime/2)/runtime)%100, skipped_frames);*/ sprintf(txt, "\n%d.%02d seconds, %d frames, %d.%02d fps (%d B frames skipped)", runtime/1000, (100*runtime/1000)%100, framenum, 1000*framenum/runtime, (100000*framenum/runtime)%100, skipped_frames); message(txt); sprintf(txt, "Frames: %d (I), %d (P), %d (B), %d (D)", i_c, p_c, b_c, d_c); message(txt); return 1;}void Mpeg2Video::usage(const char* name){ msg("usage: "); msg(name); message(" <filename> [options]"); message("options:"); message("\t-vn\tverbose output (n: level)"); message("\t-q\tquiet (no error output)"); message("\t-ds\tdisplay title (s: title)"); message("\t-fn\tframe rate (default = as fast as possible)"); message("\t-cn\tChunk size for buffer block read (NOTE: be carefull when using sychronization)"); message(""); message("\tMPEG 2 Video Player\n"); msg("\tversion "); message(RELEASE); message("\tAlex Theo de Jong (e-mail: alex.dejong@nist.gov)\n"); message("\tMulti-Media and Digital Video Group"); message("\tNational Institute of Standards and Technology"); message("\tGaithersburg, Md, U.S.A.\n\n"); message(""); message("Original code by:"); message("\tMPEG Software Simulation Group &"); message("\tStefan Eckart"); message("\tFraunhofer-Institut fuer Festkoerpertechnologie, Germany");}int Mpeg2Video::options(){ TRACER("int Mpeg2Video::options()"); if (argc<2 || argv[1][0]=='-'){ usage(argv[0]); return 0; } filename=argv[1]; for (int i=2; i<argc; i++){ if (argv[i]=='\0') break; switch (toupper(argv[i][1])){ case 'F': framerate = atoi(&argv[i][2]); ::framerate=framerate; break; case 'V': verbose = atoi(&argv[i][2]); break;#ifdef TRACE case 'T': trace=1; break;#endif case 'D': displaytitle=&argv[i][2]; break; case 'C': blockreadsize=atoi(&argv[i][2]); break; case 'Q': quiet = 1; break; default : msg("undefined option ignored - "); message(argv[i]); } } if (framerate) time_interval_usec=1000000/framerate; // in usec if (!displaytitle.length()) displaytitle="Hi there!"; return 1;}int Mpeg2Video::initdecoder(){ TRACER("int Mpeg2Video::initdecoder()"); int size; static int blk_cnt_tab[3] = {6,8,12}; if (!ld->mpeg2){ // force MPEG-1 parameters prog_seq = 1; prog_frame = 1; pict_struct = FRAME_PICTURE; frame_pred_dct = 1; chroma_format = CHROMA420; matrix_coefficients = 5; } /* round to nearest multiple of coded macroblocks */ mb_width = (horizontal_size+15)/16; mb_height = (ld->mpeg2 && !prog_seq) ? 2*((vertical_size+31)/32) : (vertical_size+15)/16; coded_picture_width = 16*mb_width; coded_picture_height = 16*mb_height; chrom_width = (chroma_format==CHROMA444) ? coded_picture_width : coded_picture_width>>1; chrom_height = (chroma_format!=CHROMA420) ? coded_picture_height : coded_picture_height>>1; blk_cnt = blk_cnt_tab[chroma_format-1]; for (int cc=0; cc<3; cc++){ if (cc==0) size = coded_picture_width*coded_picture_height; else size = chrom_width*chrom_height; refframe[cc]=new unsigned char[size]; oldrefframe[cc]=new unsigned char[size]; auxframe[cc]=new unsigned char[size]; if (ld->scalable_mode==SC_SPAT){ // this assumes lower layer is 4:2:0 llframe0[cc]=new unsigned char[(llw*llh)/(cc?4:1)]; llframe1[cc]=new unsigned char[(llw*llh)/(cc?4:1)]; } } if (ld->scalable_mode==SC_SPAT) lltmp=new short[llw*((llh*vn)/vm)]; if (!ld->display || (ld->display->init(horizontal_size, vertical_size)<0)){ error("could not initialize X11 display"); athr_exit(0); } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -