📄 mpegvideo.cpp
字号:
_thread = NULL; } ResetPause();}voidMPEGvideo:: Rewind(void){ Stop(); if ( _stream ) { /* Reinitialize vid_stream pointers */ ResetVidStream( _stream );#ifdef ANALYSIS init_stats();#endif }}voidMPEGvideo:: ResetSynchro(double time){ if( _stream ) { _stream->_jumpFrame = -1; _stream->realTimeStart = -time; play_time = time; if (time > 0) { double oneframetime; if (_stream->_oneFrameTime == 0) oneframetime = 1.0 / _stream->_smpeg->_fps; else oneframetime = _stream->_oneFrameTime; /* time -> frame */ _stream->totNumFrames = (int)(time / oneframetime); /* Set Current Frame To 0 & Frame Adjust Frag Set */ _stream->current_frame = 0; _stream->need_frameadjust=true; } }}voidMPEGvideo::Skip(float seconds){ int frame; /* Called only when there is no timestamp info in the MPEG */ /* This is quite slow however */ printf("Video: Skipping %f seconds...\n", seconds); frame = (int) (_fps * seconds); if( _stream ) { _stream->_jumpFrame = frame; while( (_stream->totNumFrames < frame) && ! _stream->film_has_ended ) { mpegVidRsrc( 0, _stream, 0 ); } ResetSynchro(0); }} /* Michel Darricau from eProcess <mdarricau@eprocess.fr> conflict name in popcorn */MPEGstatusMPEGvideo:: GetStatus(void){ if ( _stream ) { if( !_thread || (_stream->film_has_ended ) ) { return MPEG_STOPPED; } else { return MPEG_PLAYING; } } return MPEG_ERROR;}boolMPEGvideo:: GetVideoInfo(MPEG_VideoInfo *info){ if ( info ) { info->width = _ow; info->height = _oh; if ( _stream ) { info->current_frame = _stream->current_frame;#ifdef CALCULATE_FPS /* Get the appropriate indices for the timestamps */ /* Calculate the frames-per-second from the timestamps */ if ( _stream->frame_time[_stream->timestamp_index] ) { double *timestamps; double time_diff; int this_index; int last_index; timestamps = _stream->frame_time; last_index = _stream->timestamp_index; this_index = last_index - 1; if ( this_index < 0 ) { this_index = FPS_WINDOW-1; } time_diff = timestamps[this_index] - timestamps[last_index]; info->current_fps = (double)FPS_WINDOW / time_diff; } else { info->current_fps = 0.0; }#else info->current_fps = _stream->totNumFrames / (ReadSysClock() - _stream->realTimeStart);#endif } else { info->current_frame = 0; info->current_fps = 0.0; } } return(!WasError());}/* Returns zero if fails. surf - Surface to play movie on. lock - lock is held while MPEG stream is playing callback - called on every frame, for display update*/boolMPEGvideo:: SetDisplay(SDL_Surface *dst, SDL_mutex *lock, MPEG_DisplayCallback callback){ _mutex = lock; _dst = dst; _callback = callback; if ( _image ) { SDL_FreeYUVOverlay(_image); } _image = SDL_CreateYUVOverlay(_srcrect.w, _srcrect.h, SDL_YV12_OVERLAY, dst); if ( !_dstrect.w || !_dstrect.h ) { _dstrect.w = dst->w; _dstrect.h = dst->h; } if ( !_stream ) { decodeInitTables(); InitCrop(); InitIDCT(); _stream = NewVidStream( (unsigned int) BUF_LENGTH ); if( _stream ) { _stream->_smpeg = this; _stream->ditherType = FULL_COLOR_DITHER; _stream->matched_depth = dst->format->BitsPerPixel; if( mpegVidRsrc( 0, _stream, 1 ) == NULL ) { SetError("Not an MPEG video stream"); return false; } } if ( ! InitPictImages(_stream, _w, _h, _dst) ) return false; } return true;}/* If this is being called during play, the calling program is responsible for clearing the old area and coordinating with the update callback.*/voidMPEGvideo:: MoveDisplay( int x, int y ){ SDL_mutexP( _mutex ); _dstrect.x = x; _dstrect.y = y; SDL_mutexV( _mutex );}voidMPEGvideo:: ScaleDisplayXY( int w, int h ){ SDL_mutexP( _mutex ); _dstrect.w = w; _dstrect.h = h; SDL_mutexV( _mutex );}voidMPEGvideo:: SetDisplayRegion(int x, int y, int w, int h){ SDL_mutexP( _mutex ); _srcrect.x = x; _srcrect.y = y; _srcrect.w = w; _srcrect.h = h; if(_image) { SDL_FreeYUVOverlay(_image); _image = SDL_CreateYUVOverlay(_srcrect.w, _srcrect.h, SDL_YV12_OVERLAY, _dst); } SDL_mutexV( _mutex );}/* API CHANGE: This function no longer takes a destination surface and x/y You must use SetDisplay() and MoveDisplay() to set those attributes.*/voidMPEGvideo:: RenderFrame( int frame ){ _stream->need_frameadjust = true; if( _stream->current_frame > frame ) { mpeg->rewind_stream(); mpeg->next_packet(); Rewind(); } _stream->_jumpFrame = frame; while( (_stream->current_frame < frame) && ! _stream->film_has_ended ) { mpegVidRsrc( 0, _stream, 0 ); } _stream->_jumpFrame = -1;}voidMPEGvideo:: RenderFinal(SDL_Surface *dst, int x, int y){ SDL_Surface *saved_dst; int saved_x, saved_y; /* This operation can only be performed when stopped */ Stop(); /* Set (and save) the destination and location */ saved_dst = _dst; saved_x = _dstrect.x; saved_y = _dstrect.y; SetDisplay(dst, _mutex, _callback); MoveDisplay(x, y); if ( ! _stream->film_has_ended ) { /* Search for the last "group of pictures" start code */ Uint32 start_code; MPEGstream_marker * marker, * oldmarker; marker = 0; 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 <<= 8; start_code |= mpeg->copy_byte(); if ( start_code == GOP_START_CODE ) { oldmarker = marker; marker = mpeg->new_marker(-4); if( oldmarker ) mpeg->delete_marker( oldmarker ); mpeg->garbage_collect(); } } /* Set the stream to the last spot marked */ if ( ! mpeg->seek_marker( marker ) ) { mpeg->rewind_stream(); mpeg->next_packet(); } mpeg->delete_marker( marker ); _stream->buf_length = 0; _stream->bit_offset = 0; /* Process all frames without displaying any */ _stream->_skipFrame = 1; RenderFrame( INT_MAX ); mpeg->garbage_collect(); } /* Display the frame */ DisplayFrame(_stream); /* Restore the destination and location */ SetDisplay(saved_dst, _mutex, _callback); MoveDisplay(saved_x, saved_y);}/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -