zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    BitmapDrawable
    Understanding Density Independence in Android
    HttpURLConnection
    [Unity3D]事半功倍:界面插件NGUI的使用教程与实例
    lua下标
    数组形参
    Hibernate的一级缓存
    必备技术
    idea 跳转实现类-快捷键
    JavaSE面试题:单例设计模式
  • 原文地址:https://www.cnblogs.com/nanqiang/p/10973671.html
Copyright © 2011-2022 走看看