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

📄 baseclass.h

📁 linux下实现视频播放的播放器
💻 H
字号:
/* *  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$ */#ifndef BASECLASS_H#define BASECLASS_H#define MODULE "Thread"class Thread {private:    MUTEX * th_mutex;    SDL_Thread * thread;    SDL_semaphore * ack;    // 0 - exit, 1 - running    bool thread_status;protected:    // Entry point must be static    static int EntryPoint(void * pthis) { Thread *pt = (Thread*)pthis; return pt->Start(); }    // Start cannot be virtual (called from this-> pointer)    int Start() {	thread_status = true;	SDL_SemPost(ack);	DEBUG_MSG("Thread %u starting..", SDL_ThreadID());	int ret = Run();	DEBUG_MSG("Thread %u is finishing..", SDL_ThreadID());	thread_status = false;	return ret;    }    // Function to override in derived class    virtual int Run() = 0;    // Call in main thread loop    bool ThreadRun() {	MUTEX_LOCK(th_mutex);	bool status = thread_status;	MUTEX_UNLOCK(th_mutex);#ifndef RELEASE	if(status == false) {	    LOG_MSG("Thread %u is ending", SDL_ThreadID());	}#endif	return status;    }    bool ThreadPause() {#ifdef SEM_SILENT	SDL_SemWait(ack);#else	while(SDL_SemWaitTimeout(ack, 1000) == SDL_MUTEX_TIMEDOUT) {	    ERROR_MSG("Semaphore timeout expired, line: %d, thread: %u", __LINE__, SDL_ThreadID());	}#endif	MUTEX_LOCK(th_mutex);	bool ret = thread_status;	MUTEX_UNLOCK(th_mutex);	return ret;    }    Thread():thread(NULL),thread_status(false) {	th_mutex = MUTEX_CREATE();	if(th_mutex == NULL)	    throw "Thread: Failed to create mutex";	ack = SDL_CreateSemaphore(0);	if(ack == NULL) {	    MUTEX_DESTROY(th_mutex);	    throw "Thread: Failed to create semaphore";	}    }    virtual ~Thread() {	if(thread)	    TerminateThread();	MUTEX_DESTROY(th_mutex);	SDL_DestroySemaphore(ack);    }public:    void ThreadCreate() {	if(thread) {	    LOG_MSG("Thread %u already exists!?", SDL_GetThreadID(thread));	    return;	}	DEBUG_MSG("Thread %u creating new worker thread", SDL_ThreadID());	MUTEX_LOCK(th_mutex);	thread = SDL_CreateThread(EntryPoint, this);	// Wait to get ack from the thread#ifdef SEM_SILENT	SDL_SemWait(ack);#else        while(SDL_SemWaitTimeout(ack, 1000) == SDL_MUTEX_TIMEDOUT) {            ERROR_MSG("Semaphore timeout expired, line: %d, thread: %u", __LINE__, SDL_ThreadID());	}#endif	MUTEX_UNLOCK(th_mutex);	DEBUG_MSG("Worker thread %u created successfully", SDL_GetThreadID(thread));    }    void TerminateThread(bool wait = true) {	if(thread) {	    LOG_MSG("Thread %u is terminating thread %u", SDL_ThreadID(), SDL_GetThreadID(thread));	    MUTEX_LOCK(th_mutex);	    thread_status = false;	    MUTEX_UNLOCK(th_mutex);	    SDL_SemPost(ack);	    if(wait) {		SDL_WaitThread(thread, NULL);		thread = NULL;	    }	}    }    void ThreadUnpause() {	if(!SDL_SemValue(ack))	    SDL_SemPost(ack);    }    bool ThreadStatus() {	if(!thread)	    return false;	MUTEX_LOCK(th_mutex);	bool ret = thread_status;	MUTEX_UNLOCK(th_mutex);	return ret;    }};#undef MODULE// Renderer receives data from decoder in main thread and renders it in another#include "overlay.h"// Source class receives data in a seperate thread and feeds it directly to the splitter.// Open() and Close() should be called from main program. Run() should be overridden,// it runs in a seperate thread and is responsible for creating the splitter object#define MODULE "Source"class Source : public Thread {private:protected:    virtual int Run() = 0;public:    Source() {	LOG_MSG("Created source in thread %u", SDL_ThreadID());    }    virtual bool Open(CStr&) = 0;    virtual void configure(const void *) = 0;    virtual ~Source() {	LOG_MSG("Destroyed source in thread %u", SDL_ThreadID());    }};#undef MODULE// Decoder receives data from Splitter in main thread and decodes it in a seperate thread// main program is responsible for connecting the renderer#define MODULE "Decoder"struct Packet {    bool pes_flag;    unsigned int pts;    unsigned int size;    unsigned char *data;    Packet():pes_flag(false),pts(0),size(0),data(NULL) { }};class Decoder : public Thread {private:    MUTEX * dlock;protected:    unsigned char * buffer;    SDL_semaphore * data;    const bool wait;    const unsigned int buffersize;    unsigned int roffset, woffset;    void * filterinfo;    FIFO * fifo;private:    int BufferOverrun(unsigned int pos) {	LOG_MSG("Buffer overrun at pos: %d, roffset %d, data dropped", pos, roffset);	return 0;    }protected:    int LockBuffer() {	if(MUTEX_LOCK(dlock) == -1) {	    ERROR_MSG("Mutex lock failed!");	    return 0;	}	return 1;    }    int UnlockBuffer() {	if(MUTEX_UNLOCK(dlock) == -1) {	    ERROR_MSG("Mutex unlock failed!");	    return 0;	}	return 1;    }    virtual int Run() = 0;public:    Decoder(const bool w, const unsigned int buf = BUFFERSIZE):    wait(w),buffersize(buf),roffset(0),woffset(0),filterinfo(NULL),fifo(NULL) {	dlock = MUTEX_CREATE();	if(dlock == NULL)	    throw "Decoder: Failed to create mutex";	data = SDL_CreateSemaphore(0);	if(data == NULL) {	    MUTEX_DESTROY(dlock);	    throw "Decoder: Failed to create semaphore";	}	buffer = (unsigned char*)_aligned_malloc(sizeof(char)*buffersize, 64);	if(buffer == NULL) {	    MUTEX_DESTROY(dlock);	    SDL_DestroySemaphore(data);	    throw "Decoder: Failed to allocate memory for buffer";	}	SDL_memset(buffer, 0, buffersize);	LOG_MSG("Created decoder in thread %u, buffer 0x%x-0x%x", SDL_ThreadID(), buffer, buffer+buffersize);    }    void SetFilterInfo(void * f) { filterinfo = f; }    bool WriteData(Packet * packet) {	if(!ThreadStatus() && !wait) {	    DEBUG_MSG("Decoder thread not running, data dropped");	    return false;	}	if(LockBuffer()) {	    // Wrap buffer - leave some space at the end	    // (see FF_INPUT_BUFFER_PADDING_SIZE)	    if(woffset+packet->size > buffersize-8) {		// Get last pes start position		if(!packet->pes_flag) {		    unsigned int offset = fifo->GetCurrentPacket();		    woffset = woffset - offset;		    DEBUG_MSG("Buffer wrap: Copying %d bytes to pos 0", woffset);		    // If roffset is between 0 and woffset declare buffer overrun		    if((roffset < woffset) && (!BufferOverrun(woffset))) {			UnlockBuffer();			return false;		    }		    SDL_memcpy(buffer, buffer+offset, woffset);		    fifo->ResetCurrentPacket(0);		} else {		    fifo->ResetCurrentPacket(woffset);		    woffset = 0;		}	    }	    // Handle buffer overruns	    if((woffset < roffset) && (woffset + packet->size > roffset)) {		if(!BufferOverrun(woffset+packet->size)) {		    UnlockBuffer();		    return false;		}	    }	    if(buffer) {		// This is 184 bytes max		void * pt = buffer+woffset;		small_memcpy(pt, packet->data, packet->size);		// Indicate new data is present at PES start		if(packet->pes_flag) {	    	    // Add packet to fifo queue		    fifo->AddPacket(woffset, packet->pts);		}		// Advance pointers		woffset += packet->size;		DEBUG_MSG("Wrote %d bytes from %d to %d (read offset: %d)",		    packet->size, woffset - packet->size, woffset, roffset);	    } else {		ERROR_MSG("Buffer error! Dropping %d bytes", packet->size);	    }	    UnlockBuffer();	} else {	    ERROR_MSG("Error locking buffer! Data lost.");	    return false;	}	return true;    }    virtual ~Decoder() {	MUTEX_DESTROY(dlock);	SDL_DestroySemaphore(data);	if(buffer)	    _aligned_free(buffer);	LOG_MSG("Destroyed decoder in thread %u", SDL_ThreadID());    }};#undef MODULE// Splitter class receives data from Source and feeds it to the decoders#define MODULE "Splitter"class Splitter {private:protected:    // decoders    Decoder * videodec;    Decoder * audiodec;public:    Splitter():videodec(NULL),audiodec(NULL) {	LOG_MSG("Created splitter in thread %u", SDL_ThreadID());    }    virtual int ProcessData(unsigned char*, int) = 0;    virtual ~Splitter() {	SAFE_DELETE(videodec);	SAFE_DELETE(audiodec);	LOG_MSG("Destroyed splitter in thread %u", SDL_ThreadID());    }};#undef MODULE#endif // BASECLASS_H

⌨️ 快捷键说明

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