mpeg2video.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:10k
- /*
- 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("[options]");
- message("options:");
- message("t-f <s>tFilename <s> (required)");
- message("t-v <n>tverbose output (n: level)");
- message("t-qtquiet (no error output)");
- message("t-d <s>tdisplay title (s: title)");
- message("t-fr <n>tframe rate (default = as fast as possible)");
- message("t-c <n>tChunk size for buffer block read (NOTE: be carefull when using sychronization)");
- message("");
- message("tMPEG 2 Video Playern");
- 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.nn");
- 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<3){
- usage(argv[0]);
- return 0;
- }
- for (int i=1; i<argc; i++){
- if (strcmp(argv[i], "-f") == 0 && (i+1)<argc) filename=argv[++i];
- // general options
- else if (strcmp(argv[i], "-v") == 0 && (i+1)<argc) verbose=atoi(argv[++i]);
- else if (strcmp(argv[i], "-fr") == 0 && (i+1)<argc) ::framerate=atoi(argv[++i]);
- #ifdef TRACE
- else if (strcmp(argv[i], "-t") == 0) trace=1;
- #endif
- else if (strcmp(argv[i], "-d") == 0 && (i+1)<argc) displaytitle=argv[++i];
- else if (strcmp(argv[i], "-c") == 0 && (i+1)<argc) blockreadsize=atoi(argv[++i]);
- else if (strcmp(argv[i], "-q") == 0) quiet=1;
- else {
- message("unknown argument `"); message(argv[i]); message("` - ignored");
- }
- }
- 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(coded_picture_width, coded_picture_height,1,5,48*1,57*5,100,576-100)<0)){
- if (!ld->display || (ld->display->init(coded_picture_width, coded_picture_height,1,1,1,1,0,0)<0)){
- error("could not initialize X11 display");
- athr_exit(0);
- }
- return 1;
- }