📄 videohandler.cc
字号:
//// Copyright (c) 2004 by Istv醤 V醨adi//// This file is part of dxr3Player, a DVD player written specifically // for the DXR3 (aka Hollywood+) decoder card.// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program 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 General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//------------------------------------------------------------------------------#include "VideoHandler.h"#include "SPUHandler.h"#include "output/SystemTimer.h"#include "dvd/packet/PacketQueue.h"#include "dvd/packet/TimedDataBlockPacket.h"#include "dvd/packet/DataBlockTypes.h"#include "util/Reference.h"#include "util/Util.h"#include "util/Config.h"#include "unichrome/Unichrome.h"#include "unichrome/Mode.h"#include <cstring>//------------------------------------------------------------------------------using output::unichrome::VideoHandler;using output::SystemTimer;using dvd::packet::PacketQueue;using dvd::packet::TimedDataBlockPacket;using dvd::packet::DataBlockPacket;using dvd::packet::DataBlockTypes;using unichrome::Mode;using sched::Scheduler;using mpeg::SequenceHeader;using mpeg::PictureHeader;using mpeg::GOPHeader;using mpeg::QuantMatrix;using unichrome::Unichrome;using unichrome::MPEGDecoder;//------------------------------------------------------------------------------inline ptsdiff_t VideoHandler::getFrameLength() const{ return (videoAttributes.standard==PAL) ? 3600 : 3003;}//------------------------------------------------------------------------------inline ptsdiff_t VideoHandler::getTolerance() const{ return playIntra ? Util::ptsFrequency : getFrameLength()/2;}//------------------------------------------------------------------------------//------------------------------------------------------------------------------VideoHandler::VideoHandler(PacketQueue& inputQueue, SystemTimer& timer, SPUHandler& spuHandler, Unichrome& videoDevice) : MPEGParser( (MPEGListener&)*this ), inputQueue(inputQueue), videoDevice(videoDevice), timer(timer), spuHandler(spuHandler), basePTS(0), numFields(0), fieldCompensation(0), playIntra(false), nextOnlyIFrame(true){}//------------------------------------------------------------------------------void VideoHandler::run(){ Mode mode(videoAttributes.standard); videoDevice.setMode(mode); clearOSD(); videoDevice.setAspectRatio(videoAttributes.aspectRatio); spuHandler.setWideScreen(videoAttributes.aspectRatio==AR_16_9); while(!shouldQuit()) { clearInterrupt(); waitHWFlipFinished(false); parse(); } waitHWFlipFinished(false); videoDevice.stop();}//------------------------------------------------------------------------------Reference<DataBlockPacket> VideoHandler::getNextPacket(){ Reference<TimedDataBlockPacket> packet; while(!isInterrupted() && !packet.isValid()) { packet = TimedDataBlockPacket::convert(inputQueue.get(Util::currentTimeMillis()+100)); if (!packet.isValid() && !isInterrupted()) { drawCurrentFrame(false); } } return packet;}//------------------------------------------------------------------------------void VideoHandler::printStatus() const{ //Log::debug(" brightness: %u\n", brightness/2);}//------------------------------------------------------------------------------void VideoHandler::setPlayIntra(bool x){ playIntra = x; videoDevice.getMPEGDecoder().setPlayIntra(x);}//------------------------------------------------------------------------------void VideoHandler::reset(){ flush(); videoDevice.getMPEGDecoder().reset(); nextOnlyIFrame = true; MPEGParser::reset();}//------------------------------------------------------------------------------void VideoHandler::flush(){ basePTS = 0; numFields = 0; fieldCompensation = 0; videoDevice.getMPEGDecoder().flush();}//------------------------------------------------------------------------------bool VideoHandler::isDifferent(const VideoAttributes& attributes) const{ return attributes.standard!=videoAttributes.standard || attributes.aspectRatio!=videoAttributes.aspectRatio;}//------------------------------------------------------------------------------void VideoHandler::setAttributes(const VideoAttributes& attributes){ if (attributes.standard!=videoAttributes.standard) { Mode mode(attributes.standard); videoDevice.setMode(mode); clearOSD(); } if (attributes.aspectRatio!=videoAttributes.aspectRatio) { videoDevice.setAspectRatio(attributes.aspectRatio); spuHandler.setWideScreen(attributes.aspectRatio==AR_16_9); } videoAttributes = attributes;} //------------------------------------------------------------------------------unsigned VideoHandler::increaseBrightness(){ return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::decreaseBrightness(){ return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::increaseContrast(){ return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::decreaseContrast(){ return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::increaseSaturation(){ return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::decreaseSaturation(){ return 50;}//------------------------------------------------------------------------------void VideoHandler::ptsReceived(pts_t pts){ videoDevice.getMPEGDecoder().setPTS(pts);}//------------------------------------------------------------------------------void VideoHandler::sequence(const SequenceHeader& header){ videoDevice.getMPEGDecoder().startSequence(header);}//------------------------------------------------------------------------------void VideoHandler::quantMatrix(const QuantMatrix& quantMatrix){ videoDevice.getMPEGDecoder().setQuantMatrix(quantMatrix);}//------------------------------------------------------------------------------void VideoHandler::groupOfPictures(const GOPHeader& /*header*/){}//------------------------------------------------------------------------------void VideoHandler::picture(const PictureHeader& header){ videoDevice.getMPEGDecoder().startPicture(header);}//------------------------------------------------------------------------------void VideoHandler::slice(const unsigned char* data, size_t length){ videoDevice.getMPEGDecoder().addSlice(data, length);}//------------------------------------------------------------------------------void VideoHandler::endPicture(){ MPEGDecoder& mpegDecoder = videoDevice.getMPEGDecoder(); if (!mpegDecoder.isDisplayable()) return; const MPEGDecoder::PictureInfo& displayInfo = mpegDecoder.getDisplayInfo(); bool isIFrame = displayInfo.codingType==PictureHeader::CODING_I; if ((playIntra || nextOnlyIFrame) && !isIFrame) return; nextOnlyIFrame = false; timeFrame(displayInfo.pts); if (isInterrupted()) return; drawCurrentFrame(); if (isInterrupted()) return; numFields += displayInfo.numFields;}//------------------------------------------------------------------------------void VideoHandler::endSequence(){ videoDevice.getMPEGDecoder().endSequence(); endPicture();}//------------------------------------------------------------------------------void VideoHandler::clearOSD(){ size_t width, height; videoDevice.getOutputSize(width, height); videoDevice.setForeground(0xff000000); videoDevice.fillRectangle(0, 0, width, height); videoDevice.flush();}//------------------------------------------------------------------------------void VideoHandler::drawCurrentFrame(bool updateFieldCompensation){ MPEGDecoder& mpegDecoder = videoDevice.getMPEGDecoder(); if (!mpegDecoder.isDisplayable()) return; waitHWFlipFinished(updateFieldCompensation && numFields>0); if (isInterrupted()) return; mpegDecoder.displayPicture(); if (videoDevice.usingHWFlipping()) { // Even if displayPicture() was interrupted, we need to // initiate a HW flip so that the buffer index (nextV1Buffer) // remains consitent with what is displayed! if (updateFieldCompensation) { videoDevice.startHWFlip(numFields, fieldCompensation); } else { videoDevice.startHWFlip(0, 0); } }}//------------------------------------------------------------------------------pts_t VideoHandler::getFramePTS(pts_t pts){ const ptsdiff_t frameLength = getFrameLength(); pts_t framePTS = basePTS + numFields * frameLength / 2; if (pts!=INVALID_PTS) { pts_t picturePTS = pts + timer.getPTSCompensation(); if (framePTS!=picturePTS || playIntra) { if (!playIntra) { Log::debug("output::unichrome::VideoHandler::getFramePTS: framePTS=%llu, picturePTS=%llu, basePTS=%llu, numFields=%u\n", framePTS, picturePTS, basePTS, numFields); } framePTS = picturePTS; basePTS = picturePTS; numFields = 0; fieldCompensation = 0; } } else if (playIntra) { basePTS = framePTS; numFields = 0; fieldCompensation = 0; } return framePTS;}//------------------------------------------------------------------------------void VideoHandler::timeFrame(pts_t pts){ pts_t framePTS = getFramePTS(pts); if (!videoDevice.usingHWFlipping() || numFields==0) { pts_t currentSCR = timer.getCurrentSCR(); if (framePTS<currentSCR) { if ( (framePTS+getTolerance()) < currentSCR ) { ptsdiff_t diff = currentSCR - framePTS; timer.advancePTSCompensation(diff); basePTS += diff; Log::debug("output::unichrome::VideoHandler::timeFrame: advanced PTS compensation by: %lld\n", diff); } } else { if (videoDevice.usingHWFlipping()) { if (framePTS>=900) framePTS -= 900; else framePTS = 0; } timer.sleepInterruptible(framePTS); } }}//------------------------------------------------------------------------------void VideoHandler::waitHWFlipFinished(bool updateFieldCompensation){ if (!videoDevice.usingHWFlipping()) return; size_t fieldNumber; millis_t flipTime = videoDevice.waitHWFlipFinished(fieldNumber); if (!updateFieldCompensation || flipTime==INVALID_MILLIS || isInterrupted()) { return; } const ptsdiff_t frameLength = getFrameLength(); const ptsdiff_t tolerance = getTolerance(); pts_t fieldPTS = basePTS + fieldNumber * frameLength / 2; pts_t flipPTS = timer.getPTS(flipTime); if ( (fieldPTS+tolerance) < flipPTS ) { ssize_t diff = (flipPTS - fieldPTS) * 2 / frameLength; Log::debug("output::unichrome::VideoHandler::waitHWFlipFinished: skipping %d fields (fieldPTS=%llu, flipPTS=%llu)\n", diff, fieldPTS, flipPTS); fieldCompensation -= diff; } else if ( fieldPTS > (flipPTS + tolerance) ) { ssize_t diff = (fieldPTS - flipPTS) * 2 / frameLength; Log::debug("output::unichrome::VideoHandler::waitHWFlipFinished: inserting a delay of %d fields (fieldPTS=%llu, flipPTS=%llu)\n", diff, fieldPTS, flipPTS); fieldCompensation += diff; }}//------------------------------------------------------------------------------//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -