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

📄 overlay.cpp

📁 linux下实现视频播放的播放器
💻 CPP
字号:
/* *  Copyright (C) 2005-2007  gulikoza * *  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. *//* $Id$ */#include "iptv.h"#define USES_BASECLASS#include "video.h"#include "overlay.h"#include "video/output.h"//#define DEBUG#include "log.h"#define MODULE "Renderer"int Renderer::CreateOutput(OUTPUT output_mode){    // Create output class    if(output_mode < 2) {	output = new Overlay();#if (HAVE_DDRAW_H)    } else if(output_mode == DDRAW) {	output = new DDraw();#endif#if (C_OPENGL)    } else if(output_mode == OPENGL) {	output = new OpenGL();#endif    }}void Renderer::SetDeinterlace(int d){    Lock();    if(output) output->SetDeinterlace(d);    Unlock();}Renderer::~Renderer(){    SDL_SemPost(info.display_change);    TerminateThread();    SDL_DestroySemaphore(info.display_change);    for(unsigned int i = 0; i < FRAMES; i++) {        if(frames[i].data[0]) _aligned_free(frames[i].data[0]);    }    MUTEX_DESTROY(data);    MUTEX_DESTROY(display_lock);    LOG_MSG("Destroyed renderer object");}int Renderer::Run(){    // Last valid PTS and last displayed frame    int cropx = 0, cropy = 0;    unsigned int laststamp = 0, lastticks = 0;    SDL_Rect clip; clip.x = 0; clip.y = 0;    double aspect = 0.0;    Buffer buffer;    ERROR_MSG("(ThreadID: %u) init complete", SDL_ThreadID());    while(ThreadRun()) {	// Get current frame number, LockFrame will block if insufficient frames	// will return -1 if thread should quit	int i = LockFrame();	if(i < 0) {	    LOG_MSG("Got empty frame");	    if(output) {		Lock(); i = 0;		while((output->CopyData(NULL) < 0) && (i < 20)) {		    LOG_MSG("Overlay lock failed!");		    SDL_Delay(1); i++;		    if(!ThreadRun()) goto end;		}		output->SwapBuffers(&clip);		Unlock();	    }	    UnlockFrame();	    continue;	}	LOG_MSG("Processing frame %d, timestamp %d", i, frames[i].pts);	bool dropframe = false;	// Ready to display the frame	unsigned int pts = frames[i].pts;	// If frame does not have a timestamp, use last timestamp + frame duration	if(!pts) {	    pts = (unsigned int)lrint(laststamp + frames[i].time);	    LOG_MSG("Missing timestamp, using %d", pts);	}	laststamp = pts;	// Sleep until PTS	dropframe = timer->SleepPTS(pts-2);	// Protect against display mode changes	Lock();	if((info.changed) || (frames[i].changed)) {	    output->Free();	    frames[i].changed = false;	    // Adjust drawing rectagnle	    if(info.aspect == 0.0)		clip.w = (Uint16)(info.h*frames[i].aspect);	    else		clip.w = (Uint16)(info.h*info.aspect);	    clip.h = info.h;	    // Calculate crop	    cropx = info.cropx&0x3F;	    cropy = info.cropy&0x3F;	    if(info.cropy&0xF00)		cropy += (frames[i].h - (int)(frames[i].h*(4.0/3.0)*(9.0/16.0)))>>1;	    else if(info.cropy&0xF000)		cropy += (frames[i].h - (int)(frames[i].h*(4.0/3.0)*(10.0/16.0)))>>1;	    buffer.height = frames[i].h - (cropy * 2);	    buffer.src_width = frames[i].pitch;	    buffer.dst_width = frames[i].w - (cropx * 2);	    // if aspect ratio changed, resize main window	    if(((info.aspect == 0.0) && (aspect != frames[i].aspect)) ||		((info.aspect != 0.0) && (aspect != info.aspect)))  {		if(info.aspect == 0.0)		    aspect = frames[i].aspect;		else		    aspect = info.aspect;		LOG_MSG("Source video aspect ratio changed to %.2f (%d)", aspect, i);    		// Resize surface		SDL_Event event;		event.type = SDL_USEREVENT;		event.user.data1 = (void*)((intptr_t)clip.w);		event.user.data2 = (void*)((intptr_t)clip.h);		SDL_PushEvent(&event);		// Unlock mutex so display mode change can lock it		Unlock();		// Wait for ack                while((queue.GetUsed() > -1) && (SDL_SemWaitTimeout(info.display_change, 500) == SDL_MUTEX_TIMEDOUT)) {#ifndef SEM_SILENT                    ERROR_MSG("Semaphore timeout expired, line: %d, thread: %u", __LINE__, SDL_ThreadID());#endif		}		// At this point a flush could already be requested,		// check if current frame is still valid		if(queue.GetUsed() < 0) {		    ERROR_MSG("Flush requested, display mode change aborted");		    UnlockFrame();		    continue;		}		// As soon as we have surface lock mutex again		Lock();	    }	    if(clip.w > info.w) {		clip.w = info.w;		clip.h = (Uint16)(info.w/aspect);	    }	    clip.x = (info.w - clip.w) / 2;	    clip.y = (info.h - clip.h) / 2;	    LOG_MSG("New video size: %dx%d", clip.w, clip.h);	    info.changed = false;	    if((buffer.dst_width > 0) && (buffer.height > 0)) {		if(output->Create(buffer.dst_width, buffer.height, info.colorspace, info.surface) < 0) {		    ERROR_MSG("Overlay mode set failed: %s", SDL_GetError());		    Unlock();		    UnlockFrame();		    break;		}	    } else {		ERROR_MSG("Invalid video size %dx%d!", buffer.dst_width, buffer.height);	    }	}	if(GCC_UNLIKELY(dropframe)) {	    LOG_MSG("Dropping frame");	    Unlock();	    UnlockFrame();	    continue;	}	if(abs(info.offset) > cropy) {	    info.offset = cropy * (info.offset < 0 ? -1 : 1);	}	SDL_memcpy(buffer.data, frames[i].data, 3*sizeof(void*));	if(buffer.data) {	    buffer.data[0] +=  ((cropy + info.offset + frames[i].edge) * buffer.src_width) + cropx + frames[i].edge;	    buffer.data[1] += (((cropy + info.offset + frames[i].edge)>>1) * (buffer.src_width>>1)) + ((cropx + frames[i].edge)>>1);	    buffer.data[2] += (((cropy + info.offset + frames[i].edge)>>1) * (buffer.src_width>>1)) + ((cropx + frames[i].edge)>>1);	    if(output->CopyData(&buffer) == 0) {		UnlockFrame();		output->SwapBuffers(&clip);	    } else {		ERROR_MSG("Error locking overlay!");		UnlockFrame();	    }	    Unlock();#ifndef RELEASE	    int tt = timer->GetPTS();	    LOG_MSG("Frame displayed at PTS: %d (%d) last frame was %dms ago", tt, tt-pts, SDL_GetTicks()-lastticks);	    lastticks = SDL_GetTicks();#endif	} else {	    LOG_MSG("No overlay or no buffer!");	    UnlockFrame();	    Unlock();	}    }    Lock();end:    output->Free();    delete output;    Unlock();    ERROR_MSG("(ThreadID: %u) finish complete", SDL_ThreadID());    return 0;}

⌨️ 快捷键说明

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