?? overlay.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 + -