⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videohandler.cc

📁 Linux下比较早的基于命令行的DVD播放器
💻 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 "input/SDLInputHandler.h"#include "util/Reference.h"#include "util/Util.h"#include "util/Config.h"#include <X11/Xlib.h>#include <cstring>//------------------------------------------------------------------------------using output::sdl::VideoHandler;using output::SystemTimer;using dvd::packet::PacketQueue;using dvd::packet::TimedDataBlockPacket;using dvd::packet::DataBlockTypes;using input::SDLInputHandler;using sched::Scheduler;//------------------------------------------------------------------------------VideoHandler::VideoHandler(PacketQueue& inputQueue, SystemTimer& timer,                           SPUHandler& spuHandler) :    Schedulable("output::sdl::VideoHandler"),    inputQueue(inputQueue),    timer(timer),    spuHandler(spuHandler),    mpeg2dec(0),    mpeg2info(0),    basePTS(0),    nextIFramePTS(INVALID_PTS),    numFields(0),    playIntra(false),    nextOnlyIFrame(true),    screen(0),    overlay(0),    isFullScreen(false),    brightness(Config::get().defaultBrightness*2),    currentBuffer(0){    const Config& config = Config::get();    windowWidth = config.initialWindowWidth;    windowHeight = config.initialWindowHeight;    Display* display = XOpenDisplay(0);    if (display!=0) {        displayWidth = DisplayWidth(display, DefaultScreen(display));        displayHeight = DisplayHeight(display, DefaultScreen(display));        XCloseDisplay(display);    } else {        displayWidth = 800;        displayHeight = 600;    }    Log::debug("output::sdl::VideoHandler: displayWidth=%u, displayHeight=%u\n",               displayWidth, displayHeight);    for(size_t i = 0; i<3; ++i) {        for(size_t j = 0; j<3; ++j) {            frameBuffers[i][j] = 0;        }    }        setupGamma();}//------------------------------------------------------------------------------void VideoHandler::run(){    mpeg2dec = mpeg2_init();    mpeg2info = mpeg2_info(mpeg2dec);        parseMPEG();    SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE);    createScreen();        while(!shouldQuit()) {        clearInterrupt();        SDL_Event event;        while(SDL_PollEvent(&event)) {            if (event.type==SDL_KEYDOWN) {                SDLInputHandler::get().processEvent(event);            } else if (event.type==SDL_VIDEORESIZE) {                const Config& config = Config::get();                windowWidth = event.resize.w;                windowHeight =                     event.resize.w *                     config.initialWindowHeight /                     config.initialWindowWidth;                createScreen();            }        }                Reference<TimedDataBlockPacket> packet =             TimedDataBlockPacket::convert(inputQueue.get(Util::currentTimeMillis()+100));                if (!packet.isValid()) {            if (!isInterrupted()) {                redrawCurrentFrame();            }            continue;        }        assert(packet->getType()==DataBlockTypes::video);                pts_t packetPTS = packet->getPTS();        if (packetPTS!=INVALID_PTS) {            nextIFramePTS = packetPTS;        }        uint8_t* data = const_cast<uint8_t*>(packet->getData());        mpeg2_buffer(mpeg2dec, data, data + packet->getLength());        parseMPEG();    }        destroyScreen();        SDL_Quit();    mpeg2_close(mpeg2dec);}//------------------------------------------------------------------------------void VideoHandler::printStatus() const{    Log::debug("  brightness: %u\n", brightness/2);}//------------------------------------------------------------------------------void VideoHandler::reset(){    flush();    nextIFramePTS = INVALID_PTS;    nextOnlyIFrame = true;    mpeg2_close(mpeg2dec);    mpeg2dec = mpeg2_init();    mpeg2info = mpeg2_info(mpeg2dec);    parseMPEG();    interrupt();}//------------------------------------------------------------------------------void VideoHandler::flush(){    basePTS = 0;    numFields = 0;}//------------------------------------------------------------------------------void VideoHandler::setAttributes(const VideoAttributes& attributes){    videoAttributes = attributes;    spuHandler.setWideScreen(videoAttributes.aspectRatio == AR_16_9);}    //------------------------------------------------------------------------------void VideoHandler::toggleFullScreen(){    isFullScreen = !isFullScreen;    createScreen();}//------------------------------------------------------------------------------unsigned VideoHandler::increaseBrightness(){    if (brightness<200) {        brightness += 10;    }    setupGamma();    return brightness/2;}//------------------------------------------------------------------------------unsigned VideoHandler::decreaseBrightness(){    if (brightness>0) {        brightness -= 10;    }    setupGamma();    return brightness/2;}//------------------------------------------------------------------------------unsigned VideoHandler::increaseContrast(){    return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::decreaseContrast(){    return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::increaseSaturation(){    return 50;}//------------------------------------------------------------------------------unsigned VideoHandler::decreaseSaturation(){    return 50;}//------------------------------------------------------------------------------void VideoHandler::createScreen(){    bool restoreOverlay = overlay!=0;    size_t overlayWidth = 0;    size_t overlayHeight = 0;    if (restoreOverlay) {        overlayWidth = overlay->w;        overlayHeight = overlay->h;        SDL_FreeYUVOverlay(overlay);    }    size_t screenWidth = isFullScreen ? displayWidth : windowWidth;    size_t screenHeight = isFullScreen ? (screenWidth * 3 / 4) : windowHeight;    int flags = SDL_HWSURFACE|SDL_DOUBLEBUF;    if (isFullScreen) flags |= SDL_FULLSCREEN;    else flags |= SDL_RESIZABLE;    screen = SDL_SetVideoMode(screenWidth, screenHeight, 0, flags);    SDL_ShowCursor(isFullScreen ? SDL_DISABLE : SDL_ENABLE);    if (restoreOverlay) {        overlay =             SDL_CreateYUVOverlay(overlayWidth, overlayHeight, SDL_YV12_OVERLAY, screen);    }}//------------------------------------------------------------------------------void VideoHandler::setupOverlay(size_t width, size_t height){    bool isWideScreen = videoAttributes.aspectRatio==AR_16_9;    size_t overlayWidth = width;    size_t overlayHeight = isWideScreen ? width : height;    pictureHeight = height;        if (overlay==0 ||         static_cast<size_t>(overlay->w)!=overlayWidth ||         static_cast<size_t>(overlay->h)!=overlayHeight)     {        if (overlay!=0) {            SDL_FreeYUVOverlay(overlay);        }        overlay =            SDL_CreateYUVOverlay(overlayWidth, overlayHeight, SDL_YV12_OVERLAY, screen);        SDL_LockYUVOverlay(overlay);        size_t numPixels = overlayWidth * overlayHeight;        memset(overlay->pixels[0], 16, numPixels);        memset(overlay->pixels[1], 128, numPixels/4);        memset(overlay->pixels[2], 128, numPixels/4);        SDL_UnlockYUVOverlay(overlay);                SDL_DisplayYUVOverlay(overlay, &screen->clip_rect);    }}//------------------------------------------------------------------------------void VideoHandler::destroyScreen(){    if (overlay!=0) {        SDL_FreeYUVOverlay(overlay);        overlay = 0;    }}//------------------------------------------------------------------------------void VideoHandler::parseMPEG(){    int state = mpeg2_parse(mpeg2dec);    while(state!=STATE_BUFFER && !isInterrupted()) {        const mpeg2_sequence_t* sequence = mpeg2info->sequence;        switch(state) {          case STATE_SEQUENCE:            for(size_t i = 0; i<3; ++i) {                free(frameBuffers[i][0]);                frameBuffers[i][0] = (uint8_t*)malloc(sequence->width * sequence->height);                                free(frameBuffers[i][1]);                frameBuffers[i][1] = (uint8_t*)malloc(sequence->chroma_width *                                                       sequence->chroma_height);                free(frameBuffers[i][2]);                frameBuffers[i][2] = (uint8_t*)malloc(sequence->chroma_width *                                                       sequence->chroma_height);                mpeg2_set_buf(mpeg2dec, frameBuffers[i], 0);            }            currentBuffer = 0;            break;          case STATE_SLICE:          case STATE_END:          case STATE_INVALID_END:            if (mpeg2info->display_fbuf) {                unsigned pictureFlags = mpeg2info->display_picture->flags;                bool isIFrame =                     (pictureFlags&PIC_MASK_CODING_TYPE)==PIC_FLAG_CODING_TYPE_I;                if ((playIntra || nextOnlyIFrame) && !isIFrame) {                    break;                }                nextOnlyIFrame = false;                currentBuffer = mpeg2info->display_fbuf->buf;                                setupOverlay(sequence->width, sequence->height);                drawCurrentFrame();                                size_t frameLength = (videoAttributes.standard==PAL) ? 3600 : 3003;                                pts_t framePTS = basePTS + numFields * frameLength / 2;                if (isIFrame && nextIFramePTS!=INVALID_PTS) {                    pts_t picturePTS = nextIFramePTS + timer.getPTSCompensation();                    if (framePTS!=picturePTS) {                        Log::debug("output::sdl::VideoHandler::parseMPEG: framePTS=%llu, picturePTS=%llu, basePTS=%llu, numFields=%u\n",                                   framePTS, picturePTS,                                   basePTS, numFields);                        framePTS = picturePTS;                        basePTS = picturePTS;                        numFields = 0;                    }                    nextIFramePTS = INVALID_PTS;                }                pts_t currentSCR = timer.getCurrentSCR();                if (framePTS<currentSCR) {                    pts_t tolerance = playIntra ? Util::ptsFrequency : (2*frameLength);                    if ( (framePTS+tolerance) < currentSCR ) {                        ptsdiff_t diff = currentSCR - framePTS;                        timer.advancePTSCompensation(diff);                        basePTS += diff;                        Log::debug("output::sdl::VideoHandler::parseMPEG: advanced PTS compensation by: %lld\n",                                   diff);                    }                } else {                    timer.sleepInterruptible(framePTS);                    if (isInterrupted()) return;                }                               if (framePTS>=currentSCR || playIntra) {                    SDL_DisplayYUVOverlay(overlay, &screen->clip_rect);                } else {                    Log::debug("output::sdl::VideoHandler::parseMPEG: skipped the display of a frame\n");                }                numFields += mpeg2info->display_picture->nb_fields;            }            break;        }        Scheduler::yield("output::sdl::VideoHandler::parseMPEG");        if (!isInterrupted()) {            state = mpeg2_parse(mpeg2dec);        }    }}//------------------------------------------------------------------------------void VideoHandler::drawCurrentFrame(){    assert(overlay!=0);    assert(currentBuffer!=0);    SDL_LockYUVOverlay(overlay);        size_t numPixels = overlay->w * pictureHeight;    size_t overlaySize = overlay->h * overlay->w;    size_t stripSize =  (overlaySize - numPixels) / 2;    size_t bottomStripBegin = (overlaySize + numPixels) / 2;        memset(overlay->pixels[0], 16, stripSize);    memset(overlay->pixels[0]+bottomStripBegin, 16, stripSize);    if (brightness==100) {        memcpy(overlay->pixels[0] + stripSize, currentBuffer[0], numPixels);    } else {        uint8_t* dest = overlay->pixels[0] + stripSize;        uint8_t* src = currentBuffer[0];            for(size_t i = 0; i<numPixels; ++i, dest++, src++) {            *dest = gamma_y[*src];        }    }    numPixels/=4;    stripSize/=4;    bottomStripBegin/=4;        memset(overlay->pixels[1], 128, stripSize);    memset(overlay->pixels[1] + bottomStripBegin, 128, stripSize);    memcpy(overlay->pixels[1] + stripSize, currentBuffer[2], numPixels);    memset(overlay->pixels[2], 128, stripSize);    memset(overlay->pixels[2] + bottomStripBegin, 128, stripSize);    memcpy(overlay->pixels[2] + stripSize, currentBuffer[1], numPixels);        spuHandler.embedInto(overlay);    SDL_UnlockYUVOverlay(overlay);}//------------------------------------------------------------------------------void VideoHandler::redrawCurrentFrame(){    if (overlay!=0 && currentBuffer!=0 && !playIntra) {        drawCurrentFrame();        SDL_DisplayYUVOverlay(overlay, &screen->clip_rect);    }}//------------------------------------------------------------------------------void VideoHandler::setupGamma(){    if (brightness==100) return;    for(size_t i = 0; i<256; ++i) {        unsigned x = i * brightness / 100;        if (x>255) x = 255;        gamma_y[i] = x;    }}//------------------------------------------------------------------------------//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -