簡單播放器ide
MyQueue.hoop
#pragma once #include <Windows.h> #include <vector> #include <SDL.h> using namespace std; typedef struct T_Data { public: T_Data() { m_pBuf = NULL; m_iLen = 0; m_iBufLen = 0; } char *m_pBuf; int m_iLen; int m_iBufLen; }T_Data; class CMyQueue { public: CMyQueue(void); ~CMyQueue(); bool PushData(char *pData, int iLen); T_Data *PopData(); bool AddFreeDataToV(T_Data *); void QueueExit(); int QueueSize(); void CleanBuf(); public: vector<T_Data *> m_vData; vector<T_Data *> m_vFree; bool m_bLoop; unsigned int m_iPacketNum; SDL_mutex *m_mutex; // SDL_cond *m_cond; // 條件變量 };
MyQueue.cppthis
#include "MyQueue.h" CMyQueue::CMyQueue(void) { m_mutex = SDL_CreateMutex(); m_cond = SDL_CreateCond(); m_bLoop = true; m_iPacketNum = 0; } CMyQueue::~CMyQueue() { m_bLoop = false; int iCoune = m_vFree.size(); while (iCoune > 0) { T_Data *pstData = m_vFree.at(0); m_vFree.erase(m_vFree.begin()); if (pstData) { if (pstData->m_pBuf) { delete [] pstData->m_pBuf; pstData->m_pBuf = NULL; } delete pstData; pstData = NULL; } iCoune--; } iCoune = m_vData.size(); while (iCoune > 0) { T_Data *pstData = m_vData.at(0); m_vData.erase(m_vData.begin()); if (pstData) { if (pstData->m_pBuf) { delete [] pstData->m_pBuf; pstData->m_pBuf = NULL; } delete pstData; pstData = NULL; } iCoune--; } SDL_DestroyMutex(m_mutex); SDL_DestroyCond(m_cond); } bool CMyQueue::PushData(char *pData, int iLen) { bool bRet = true; if (NULL == pData || 0 >= iLen || !m_bLoop) { return false; } SDL_LockMutex(m_mutex); if (m_vFree.size() > 0) { T_Data *stTemp = m_vFree.at(0); m_vFree.erase(m_vFree.begin()); if (stTemp->m_iBufLen >= iLen) { memcpy(stTemp->m_pBuf, pData, iLen); stTemp->m_iLen = iLen; } else { delete [] stTemp->m_pBuf; stTemp->m_iBufLen = stTemp->m_iLen = iLen; stTemp->m_pBuf = new char[iLen]; memcpy(stTemp->m_pBuf, pData, iLen); } m_vData.push_back(stTemp); } else { T_Data *stTemp = new T_Data; if (stTemp) { stTemp->m_iBufLen = stTemp->m_iLen = iLen; stTemp->m_pBuf = new char[iLen]; memcpy(stTemp->m_pBuf, pData, iLen); m_vData.push_back(stTemp); } else { bRet = false; } } m_iPacketNum++; SDL_CondSignal(m_cond); SDL_UnlockMutex(m_mutex); return bRet; } T_Data *CMyQueue::PopData() { T_Data *pstData = NULL; SDL_LockMutex(m_mutex); while (m_bLoop) { if (m_vData.size() > 0) { pstData = m_vData.at(0); m_vData.erase(m_vData.begin()); m_iPacketNum--; break; } else { SDL_CondWait(m_cond, m_mutex); } } SDL_UnlockMutex(m_mutex); return pstData; } bool CMyQueue::AddFreeDataToV(T_Data * pFree) { SDL_LockMutex(m_mutex); m_vFree.push_back(pFree); SDL_UnlockMutex(m_mutex); return true; } void CMyQueue::QueueExit() { m_bLoop = false; SDL_CondSignal(m_cond); } int CMyQueue::QueueSize() { return m_iPacketNum; } void CMyQueue::CleanBuf() { SDL_LockMutex(m_mutex); while (m_vData.size() > 0) { T_Data *pstData = m_vData.at(0); m_vData.erase(m_vData.begin()); m_vFree.push_back(pstData); } m_iPacketNum = 0; SDL_UnlockMutex(m_mutex); }
cplayer.hspa
#ifndef CPLAYER_H #define CPLAYER_H #include <QObject> #include <QWidget> #include <QThread> #include "MyQueue.h" #include "SDL.h" class CPlayer { public: CPlayer(); ~CPlayer(); void SetWinID(void*id){m_pWinID = id;} void SetRect(int x, int y, int w, int h){m_rect.x = x; m_rect.y = y; m_rect.w = w; m_rect.h = h;} void PushVideo(char *pData, int iLen); static DWORD WINAPI ThreadPlay(LPVOID p); void PlayVideo(); void SDLInit(); void SDLUninit(); int CutBandYUV(char*pInBuf, int width, int height, char *pOutBuf, int x, int y, int w, int h); public: SDL_Rect m_rect; SDL_Window *m_pWindow; SDL_Texture* m_pTexture; SDL_Renderer* m_pRenderer; CMyQueue *m_pVideoQueue; HANDLE m_hThread; bool m_bLoop; void* m_pWinID; }; #endif // CPLAYER_H
cplayer.cppcode
#include "cplayer.h" extern int g_iWidth; extern int g_iHeiht; CPlayer::CPlayer() { m_pWinID = NULL; m_pTexture = NULL; m_pRenderer = NULL; m_pVideoQueue = NULL; m_pWindow = NULL; m_hThread = NULL; m_bLoop = false; } CPlayer::~CPlayer() { SDLUninit(); } void CPlayer::SDLInit() { if (NULL == m_pVideoQueue) { m_pVideoQueue = new CMyQueue; } if(NULL == m_pWindow) { m_pWindow = SDL_CreateWindowFrom((void*)m_pWinID); } else { return; } if (NULL == m_pRenderer) { m_pRenderer = SDL_CreateRenderer( m_pWindow, -1, SDL_RENDERER_ACCELERATED); } if (NULL == m_pRenderer) { m_pRenderer = SDL_CreateRenderer( m_pWindow, -1, SDL_RENDERER_SOFTWARE); } if (NULL == m_pRenderer) { return; } if (NULL == m_pTexture) { int w, h; SDL_GetWindowSize(m_pWindow, &w, &h); m_pTexture = SDL_CreateTexture( m_pRenderer,SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, g_iWidth, g_iHeiht ); } else { return; } if(NULL == m_hThread) { m_bLoop = true; m_hThread = CreateThread(NULL, 0, ThreadPlay, this, 0, NULL); } } void CPlayer::SDLUninit() { m_bLoop = false; if (m_pVideoQueue) { m_pVideoQueue->QueueExit(); } if (m_hThread) { WaitForSingleObject(m_hThread, INFINITE); CloseHandle(m_hThread); m_hThread = NULL; } if (m_pVideoQueue) { delete m_pVideoQueue; m_pVideoQueue = NULL; } if (m_pTexture) { SDL_DestroyTexture(m_pTexture); m_pTexture = NULL; } if (m_pRenderer) { SDL_DestroyRenderer(m_pRenderer); m_pRenderer = NULL; } if (m_pWindow) { //SDL_DestroyWindow(m_SDLScreen); m_pWindow = NULL; } } void CPlayer::PushVideo(char *pData, int iLen) { if (NULL == m_hThread) { SDLInit(); } if (m_pVideoQueue && m_pTexture) { m_pVideoQueue->PushData(pData, iLen); } } DWORD WINAPI CPlayer::ThreadPlay(LPVOID p) { CPlayer *pPlay = (CPlayer*)p; if(pPlay) { pPlay->PlayVideo(); } return 0; } void CPlayer::PlayVideo() { int w = 0, h = 0; if (m_pWindow) { SDL_GetWindowSize(m_pWindow, &w, &h); } int OutLen = w * h * 3 / 2; char *outBuf = new char[OutLen]; while (m_bLoop) { T_Data *pstData = m_pVideoQueue->PopData(); if(NULL == pstData) { QThread::msleep(10); continue; } char *pData = pstData->m_pBuf; int iLen = pstData->m_iLen; //CutBandYUV(pData, g_iWidth, g_iHeiht, outBuf, m_rect.x, m_rect.y, m_rect.w, m_rect.h); if (m_pTexture) { SDL_UpdateTexture( m_pTexture, NULL, pData, g_iWidth); SDL_RenderClear( m_pRenderer ); // SDL_RenderCopy( m_pRenderer, m_pTexture, &m_rect, NULL);//只顯示m_rect範圍的內容 SDL_RenderCopy( m_pRenderer, m_pTexture, NULL, NULL);//顯示完整內容 SDL_RenderPresent( m_pRenderer ); } m_pVideoQueue->AddFreeDataToV(pstData); } if(outBuf) { delete [] outBuf; outBuf = NULL; } } int CPlayer::CutBandYUV(char*pInBuf, int width, int height, char *pOutBuf, int new_x, int new_y, int new_width, int new_height) { int x = 0; int y = 0; if (NULL == pInBuf || 0 == width || 0 == height) return -1; char *pUBuf = pOutBuf + new_width * new_height; char *pVBuf = pOutBuf + new_width * new_height * 5 / 4; for (x = 0; x < new_width; x++) { for (y = 0; y < new_height; y++) //每一個循環寫一列 { *(pOutBuf + y * new_width + x) = *(pInBuf + (x + new_x) + width * (y + new_y)); //cope Y int ret = (y + new_y) % 2; if (1 == (x + new_x) % 2 && 1 == (y + new_y) % 2) { long pix = width * height + (width >> 1) * ((y + new_y) >> 1) + (((x + new_x)) >> 1); *(pUBuf + (new_width / 2)*(y / 2) + x / 2) = *(pInBuf + pix); //cope U pix += width * height / 4; *(pVBuf + (new_width / 2)*(y / 2) + x / 2) = *(pInBuf + pix); //cope V } } } return 0; }