MyPlayer

简单播放器

MyQueue.h

#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.cpp

#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.h

#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.cpp

#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;
}

 

posted @ 2019-06-04 15:07  cicero  阅读(431)  评论(0编辑  收藏  举报