📄 spuhandler.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 "SPUHandler.h"#include "Timer.h"#include "dvd/packet/PacketQueue.h"#include "dvd/packet/TimedDataBlockPacket.h"#include "dvd/packet/SPUPalettePacket.h"#include "dvd/packet/DemultiplexerParameterPacket.h"#include "dvd/spu/ControlSequence.h"#include "sched/Scheduler.h"//------------------------------------------------------------------------------using output::SPUHandler;using output::Timer;using dvd::packet::PacketQueue;using dvd::packet::Packet;using dvd::packet::TimedDataBlockPacket;using dvd::packet::SPUPalettePacket;using dvd::packet::DemultiplexerParameterPacket;using dvd::spu::SPUBufferBitReader;using dvd::spu::SPU;using dvd::spu::ControlSequence;using sched::Scheduler;//------------------------------------------------------------------------------//------------------------------------------------------------------------------SPUHandler::DisplayController::DisplayController(SPUHandler& spuHandler) : Schedulable("output::SPUHandler::DisplayController", defaultStackSize), spuHandler(spuHandler), forcedOnly(false), hasControlSequences("output::SPUHandler::DisplayController", "hasControlSequences"){} //------------------------------------------------------------------------------void SPUHandler::DisplayController::run(){ while(!shouldQuit()) { clearInterrupt(); while(controlSequences.empty() && !isInterrupted()) { Scheduler::wait(hasControlSequences); } for(controlSequences_t::iterator i = controlSequences.begin(); i!=controlSequences.end() && !isInterrupted();) { controlSequences_t::iterator current = i; ++i; ControlSequence* controlSequence = *current; controlSequences.erase(current); pts_t pts = controlSequence->getPTS() + spuHandler.timer.getPTSCompensation(); ControlSequence::displayCommand_t displayCommand = controlSequence->getDisplayCommand(); switch(displayCommand) { case ControlSequence::FORCED_START: case ControlSequence::START: { if (forcedOnly && displayCommand!=ControlSequence::FORCED_START) break; if (!controlSequence->getPicture()->isValid()) break; spuHandler.timer.sleepInterruptible(pts); if (!isInterrupted()) { spuHandler.setPicture(*controlSequence); } } break; case ControlSequence::STOP: spuHandler.timer.sleepInterruptible(pts); spuHandler.resetPicture(); break; default: break; } delete controlSequence; } }}//------------------------------------------------------------------------------ void SPUHandler::DisplayController::reset(){ for(controlSequences_t::const_iterator i = controlSequences.begin(); i!=controlSequences.end(); ++i) { delete *i; } controlSequences.clear(); interrupt();}//------------------------------------------------------------------------------void SPUHandler::DisplayController::setForcedOnly(bool fo){ forcedOnly = fo;}//------------------------------------------------------------------------------ void SPUHandler::DisplayController::addSPU(SPU& spu){ spu.appendControlSequencesTo(controlSequences); hasControlSequences.set();}//------------------------------------------------------------------------------//------------------------------------------------------------------------------SPUHandler::SPUHandler(PacketQueue& inputQueue, Timer& timer) : Schedulable("output::SPUHandler", defaultStackSize, 2), displayController(*this), inputQueue(inputQueue), timer(timer), spuPTS(INVALID_PTS), pictureForced(false), pictureColor(0), pictureContrast(0), showButton(false), buttonColor(0), buttonContrast(0){}//------------------------------------------------------------------------------void SPUHandler::run(){ while(!shouldQuit()) { clearInterrupt(); Reference<Packet> packet = inputQueue.get(); if (!packet.isValid()) continue; Reference<TimedDataBlockPacket> dataPacket = TimedDataBlockPacket::convert(packet); if (dataPacket.isValid()) { packet = 0; processDataPacket(dataPacket); continue; } Reference<SPUPalettePacket> palettePacket = SPUPalettePacket::convert(packet); if (palettePacket.isValid()) { setPalette(palettePacket->getPalette()); continue; } Reference<DemultiplexerParameterPacket> demultiplexerParameterPacket = DemultiplexerParameterPacket::convert(packet); if (demultiplexerParameterPacket.isValid()) { displayController. setForcedOnly(demultiplexerParameterPacket->parameters.spuForcedOnly); continue; } }}//------------------------------------------------------------------------------void SPUHandler::reset(){ displayController.reset(); spuPTS = INVALID_PTS; picture = 0; showButton = false; spuBuffer.reset(); update(); interrupt();}//------------------------------------------------------------------------------void SPUHandler::setWideScreen(bool ws){ wideScreen = ws;}//------------------------------------------------------------------------------void SPUHandler::highlightButton(int color, int contrast, size_t top, size_t bottom, size_t left, size_t right){ Area newArea(left, right, top, bottom); if (!showButton || !(buttonVisibleArea==newArea) || buttonColor!=color || buttonContrast!=contrast) { buttonVisibleArea = newArea; buttonColor = color; buttonContrast = contrast; showButton = true; update(); }} //------------------------------------------------------------------------------void SPUHandler::clearButton(){ if (showButton) { showButton = false; update(); }}//------------------------------------------------------------------------------inline const Area& SPUHandler::getVisibleArea(displayEntity_t displayEntity) const{ switch(displayEntity) { case PICTURE: default: return pictureVisibleArea; break; case BUTTON: return buttonVisibleArea; break; }}//------------------------------------------------------------------------------bool SPUHandler::isDisplayable(displayEntity_t displayEntity) const{ const Area& area = getVisibleArea(displayEntity); return picture.isValid() && (displayEntity==PICTURE || showButton) && area.getStartX() >= picture->getXOffset() && area.getStartY() >= picture->getYOffset();}//------------------------------------------------------------------------------const unsigned char* SPUHandler::getVisiblePictureData(displayEntity_t displayEntity, size_t& pictureWidth, size_t& startX, size_t& startY, size_t& width, size_t& height) const{ const Area& area = getVisibleArea(displayEntity); pictureWidth = picture->getWidth(); startX = area.getStartX(); startY = area.getStartY(); width = area.getWidth(); height = area.getHeight(); if (wideScreen) { startY *= 4; startY /= 3; startY -= 16; height *= 4; height /= 3; } return picture->getData() + picture->getWidth() * (area.getStartY() - picture->getYOffset()) + (area.getStartX() - picture->getXOffset());}//------------------------------------------------------------------------------void SPUHandler::processDataPacket(Reference<TimedDataBlockPacket>& packet){ const unsigned char* data = packet->getData(); size_t length = packet->getLength(); pts_t packetPTS = packet->getPTS() + timer.getPTSCompensation(); while(length>0 && !isInterrupted()) { if (spuBuffer.isEmpty()) { spuPTS = packetPTS; packetPTS = INVALID_PTS; } size_t added = spuBuffer.add(data, length); length -= added; data += added; if (length==0) { packet=0; } if (spuBuffer.isFull()) { Scheduler::yield("output::sdl::SPUHandler::processDataPacket"); SPUBufferBitReader spuReader(spuBuffer); spu.reset(); spu.decode(spuReader); pts_t basePTS = spuPTS; spuPTS = INVALID_PTS; if (basePTS==INVALID_PTS) { basePTS = timer.getCurrentSCR(); } spu.setPTS(basePTS); displayController.addSPU(spu); spuBuffer.reset(); } }}//------------------------------------------------------------------------------void SPUHandler::setPicture(const ControlSequence& controlSequence){ picture = controlSequence.getPicture(); pictureForced = controlSequence.getDisplayCommand()==ControlSequence::FORCED_START; pictureColor = controlSequence.getColorIndex(); pictureContrast = controlSequence.getContrast(); pictureVisibleArea.reset(); picture->getVisibleArea(pictureVisibleArea); update();} //------------------------------------------------------------------------------void SPUHandler::resetPicture(){ picture = 0; update();}//------------------------------------------------------------------------------void SPUHandler::update(){}//------------------------------------------------------------------------------//------------------------------------------------------------------------------// Local Variables:// mode: C++// c-basic-offset: 4// indent-tabs-mode: nil// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -