📄 mpegvideo.cpp
字号:
/* SMPEG - SDL MPEG Player Library Copyright (C) 1999 Loki Entertainment Software - Modified by Michel Darricau from eProcess <mdarricau@eprocess.fr> for popcorn - This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//* * 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. *//* * Portions of this software Copyright (c) 1995 Brown University. * 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 BROWN UNIVERSITY 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 BROWN * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * BROWN UNIVERSITY 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 BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *//* Changes to make the code reentrant: Got rid of setjmp, longjmp deglobalized: EOF_flag, FilmState, curVidStream, bitOffset, bitLength, bitBuffer, sys_layer, input, seekValue, window, X Windows globals (to xinfo), curBits, ditherType, matched_depth, totNumFrames, realTimeStart Additional changes: Ability to play >1 movie (w/out CONTROLS) Make sure we do a full frame for each movie DISABLE_DITHER #ifdef to avoid compiling dithering code Changes to deal with non-MPEG streams Now deals with NO_DITHER, PPM_DITHER and noDisplayFlag==1 CONTROLS version now can deal with >1 movie -lsh@cs.brown.edu (Loring Holden)*/#include <limits.h>#include <string.h>#include "video.h"#include "proto.h"#include "dither.h"#include "util.h"#include "MPEGvideo.h"#include "MPEGfilter.h"/*--------------------------------------------------------------*//* Define buffer length. */#define BUF_LENGTH 80000/* TODO: Eliminate these globals so multiple movies can be played. *//* Quiet flag (verbose). */int quietFlag = 1;/* Framerate, -1: specified in stream (default) 0: as fast as possible N (N>0): N frames/sec */#ifdef TIME_MPEGint framerate = 0;#elseint framerate = -1;#endif/* Flag for high quality at the expense of speed */#ifdef QUALITYint qualityFlag = 1;#elseint qualityFlag = 0;#endif/*--------------------------------------------------------------*/MPEGvideo::MPEGvideo(MPEGstream *stream){ Uint32 start_code; MPEGstream_marker *marker; /* Set the MPEG data stream */ mpeg = stream; time_source = NULL; /* Set default playback variables */ _thread = NULL; _dst = NULL; _mutex = NULL; _stream = NULL; /* Mark the data to leave the stream unchanged */ /* after parsing */ marker = mpeg->new_marker(0); /* Get the width and height of the video */ start_code = mpeg->copy_byte(); start_code <<= 8; start_code |= mpeg->copy_byte(); start_code <<= 8; start_code |= mpeg->copy_byte(); while ( ! mpeg->eof() && (start_code != SEQ_START_CODE) ) { start_code <<= 8; start_code |= mpeg->copy_byte(); } if ( start_code == SEQ_START_CODE ) { Uint8 buf[4]; /* Get the width and height of the video */ mpeg->copy_data(buf, 4); _w = (buf[0]<<4)|(buf[1]>>4); /* 12 bits of width */ _h = ((buf[1]&0xF)<<8)|buf[2]; /* 12 bits of height */ switch(buf[3]&0xF) /* 4 bits of fps */ { case 1: _fps = 23.97f; break; case 2: _fps = 24.00f; break; case 3: _fps = 25.00f; break; case 4: _fps = 29.97f; break; case 5: _fps = 30.00f; break; case 6: _fps = 50.00f; break; case 7: _fps = 59.94f; break; case 8: _fps = 60.00f; break; case 9: _fps = 15.00f; break; default: _fps = 30.00f; break; } } else { _w = 0; _h = 0; _fps = 0.00; SetError("Not a valid MPEG video stream"); } /* Rewind back to the old position */ mpeg->seek_marker(marker); mpeg->delete_marker(marker); /* Keep original width and height in _ow and _oh */ _ow = _w; _oh = _h; /* Now round up width and height to a multiple */ /* of a macroblock size (16 pixels) to keep the */ /* video decoder happy */ _w = (_w + 15) & ~15; _h = (_h + 15) & ~15; /* Set the default playback area */ _dstrect.x = 0; _dstrect.y = 0; _dstrect.w = 0; _dstrect.h = 0; /* Set the source area */ _srcrect.x = 0; _srcrect.y = 0; _srcrect.w = _ow; _srcrect.h = _oh; _image = 0; _filter = SMPEGfilter_null(); _filter_mutex = SDL_CreateMutex();// printf("[MPEGvideo::MPEGvideo]_filter_mutex[%lx] = SDL_CreateMutex()\n",_filter_mutex);}MPEGvideo:: ~MPEGvideo(){ /* Stop it before we free everything */ Stop(); /* Free actual video stream */ if( _stream ) DestroyVidStream( _stream ); /* Free overlay */ if(_image) SDL_FreeYUVOverlay(_image); /* Release filter */ SDL_DestroyMutex(_filter_mutex); _filter->destroy(_filter);}/* Simple thread play function */int Play_MPEGvideo( void *udata ){ MPEGvideo *mpeg = (MPEGvideo *)udata; /* Get the time the playback started */ mpeg->_stream->realTimeStart += ReadSysClock();#ifdef TIME_MPEG int start_frames, stop_frames; int total_frames; Uint32 start_time, stop_time; float total_time; start_frames = mpeg->_stream->totNumFrames; start_time = SDL_GetTicks();#endif while( mpeg->playing ) { int mark = mpeg->_stream->totNumFrames; /* make sure we do a whole frame */ while( mark == mpeg->_stream->totNumFrames ) { mpegVidRsrc( 0, mpeg->_stream, 0 ); } if( mpeg->_stream->film_has_ended ) { mpeg->playing = false; } } /* Get the time the playback stopped */ mpeg->_stream->realTimeStart -= ReadSysClock();#ifdef TIME_MPEG stop_time = SDL_GetTicks(); stop_frames = mpeg->_stream->totNumFrames; total_frames = (stop_frames-start_frames); total_time = (float)(stop_time-start_time)/1000.0; if ( total_time > 0 ) { printf("%d frames in %2.2f seconds (%2.2f FPS)\n", total_frames, total_time, (float)total_frames/total_time); }#endif return(0);}voidMPEGvideo:: Play(void){ ResetPause(); if ( _stream ) { if ( playing ) { Stop(); } playing = true;#ifdef PROFILE_VIDEO /* Profiling doesn't work well with threads */ Play_MPEGvideo(this);#else _thread = SDL_CreateThread( Play_MPEGvideo, this ); if ( !_thread ) { playing = false; }#endif }}voidMPEGvideo:: Stop(void){ if ( _thread ) { playing = false; SDL_WaitThread(_thread, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -