Windows 视频解码及显示[转]

Windows 视频解码及显示[转]

目录

创建窗口

单线程解码并且绘制

多线程解码并且绘制

速率控制

创建窗口

#pragma once

#include <windows.h>
#include <tchar.h>

LRESULT CALLBACK    windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC         hdc;
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_SIZE:
        break;
    case WM_CLOSE:
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        break;
    }

    return  DefWindowProc(hWnd, msg, wParam, lParam);
}

int     WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    //  1   注册窗口类
    ::WNDCLASSEXA winClass;
    winClass.lpszClassName = "FFVideoPlayer";
    winClass.cbSize = sizeof(::WNDCLASSEX);
    winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
    winClass.lpfnWndProc = windowProc;
    winClass.hInstance = hInstance;
    winClass.hIcon = 0;
    winClass.hIconSm = 0;
    winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    winClass.hbrBackground = (HBRUSH)(BLACK_BRUSH);
    winClass.lpszMenuName = NULL;
    winClass.cbClsExtra = 0;
    winClass.cbWndExtra = 0;
    RegisterClassExA(&winClass);

    //  2 创建窗口
    HWND    hWnd = CreateWindowEx(
        NULL,
        "FFVideoPlayer",
        "FFVideoPlayer",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        0,
        0,
        480,
        320,
        0,
        0,
        hInstance,
        0
        );

    UpdateWindow(hWnd);
    ShowWindow(hWnd, SW_SHOW);

    MSG     msg = { 0 };
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return  0;
}

单线程解码并且绘制

#pragma once
#include <windows.h>
#include <tchar.h>
#include "FFVideoReader.hpp"

HBITMAP         g_hBmp = 0;
HDC             g_hMem = 0;
BYTE* g_imageBuf = 0;
FFVideoReader   g_reader;

LRESULT CALLBACK    windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC         hdc;
        hdc = BeginPaint(hWnd, &ps);
        BitBlt(hdc, 0, 0, g_reader._screenW, g_reader._screenH, g_hMem, 0, 0, SRCCOPY);
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_SIZE:
        break;
    case WM_CLOSE:
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_TIMER:
    {
        BYTE* data = (BYTE*)g_reader.readFrame();
        for (int i = 0; i < g_reader._screenW * g_reader._screenH * 3; i += 3)
        {  //RGB  -> BGR
            g_imageBuf[i + 0] = data[i + 2];
            g_imageBuf[i + 1] = data[i + 1];
            g_imageBuf[i + 2] = data[i + 0];
        }
        InvalidateRect(hWnd, 0, 0);  //窗口刷新 调用WM_PAINT
    }
    break;
    default:
        break;
    }

    return  DefWindowProc(hWnd, msg, wParam, lParam);
}

void  getResourcePath(HINSTANCE hInstance, char pPath[1024])
{
    char    szPathName[1024];
    char    szDriver[64];
    char    szPath[1024];
    GetModuleFileNameA(hInstance, szPathName, sizeof(szPathName));
    _splitpath(szPathName, szDriver, szPath, 0, 0);
    sprintf(pPath, "%s%s", szDriver, szPath);
}

int     WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    //  1   注册窗口类
    ::WNDCLASSEXA winClass;
    winClass.lpszClassName = "FFVideoPlayer";
    winClass.cbSize = sizeof(::WNDCLASSEX);
    winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
    winClass.lpfnWndProc = windowProc;
    winClass.hInstance = hInstance;
    winClass.hIcon = 0;
    winClass.hIconSm = 0;
    winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    winClass.hbrBackground = (HBRUSH)(BLACK_BRUSH);
    winClass.lpszMenuName = NULL;
    winClass.cbClsExtra = 0;
    winClass.cbWndExtra = 0;
    RegisterClassExA(&winClass);

    //  2 创建窗口
    HWND    hWnd = CreateWindowEx(
        NULL,
        "FFVideoPlayer",
        "FFVideoPlayer",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        0,
        0,
        480,
        320,
        0,
        0,
        hInstance,
        0
        );

    UpdateWindow(hWnd);
    ShowWindow(hWnd, SW_SHOW);

    char    szPath[1024];
    char    szPathName[1024];

    getResourcePath(hInstance, szPath);

    sprintf(szPathName, "%sdata/11.flv", szPath);



    HDC     hDC = GetDC(hWnd);
    g_hMem = ::CreateCompatibleDC(hDC);
    g_reader.setup();
    g_reader.load(szPathName);

    BITMAPINFO	bmpInfor = { 0 };
    bmpInfor.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfor.bmiHeader.biWidth = g_reader._screenW;
    bmpInfor.bmiHeader.biHeight = -g_reader._screenH;
    bmpInfor.bmiHeader.biPlanes = 1;
    bmpInfor.bmiHeader.biBitCount = 24;
    bmpInfor.bmiHeader.biCompression = BI_RGB;
    bmpInfor.bmiHeader.biSizeImage = 0;
    bmpInfor.bmiHeader.biXPelsPerMeter = 0;
    bmpInfor.bmiHeader.biYPelsPerMeter = 0;
    bmpInfor.bmiHeader.biClrUsed = 0;
    bmpInfor.bmiHeader.biClrImportant = 0;

    g_hBmp = CreateDIBSection(hDC, &bmpInfor, DIB_RGB_COLORS, (void**)&g_imageBuf, 0, 0);
    SelectObject(g_hMem, g_hBmp);

    SetTimer(hWnd, 1, 40, 0);

    MSG     msg = { 0 };
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return  0;
}

多线程解码并且绘制

#pragma once

#include <windows.h>

class   Thread
{
public:
    DWORD               _threadId;
    HANDLE              _thread;
protected:
   
    /**
    *   线程入口函数
    */
    static  DWORD    CALLBACK threadEnter(void* pVoid)
    {
        Thread* pThis   =   (Thread*)pVoid;
        if (pThis)
        {
            pThis->run();
        }
        return  0;
    }
public:
    Thread()
    {
        _thread     =   0;
        _threadId   =   0;
    }
    virtual ~Thread()
    {
        join();
    }
   
    virtual bool    run()
    {
        return  true;
    }
    /**
    *   启动线程函数
    */
    virtual bool    start()
    {
        if (_thread != 0)
        {
            return  false;
        }
        else
        {
            //HIGH_PRIORITY_CLASS
            _thread     =   CreateThread(0,0,&Thread::threadEnter,this,0,&_threadId);
            return  true;
        }
    }
    /**
    *   等待退出函数
    */
    virtual void    join()
    {
        if (_thread)
        {
            WaitForSingleObject(_thread,0xFFFFFFFF);
            CloseHandle(_thread);
            _thread     =   0;
        }
    }
};
#include <windows.h>
#include <tchar.h>
#include "FFVideoReader.hpp"
#include "Thread.hpp"
#define WM_UPDATE_VIDEO WM_USER + 100

void  getResourcePath(HINSTANCE hInstance, char pPath[1024])
{
    char    szPathName[1024];
    char    szDriver[64];
    char    szPath[1024];
    GetModuleFileNameA(hInstance, szPathName, sizeof(szPathName));
    _splitpath(szPathName, szDriver, szPath, 0, 0);
    sprintf(pPath, "%s%s", szDriver, szPath);
}

BYTE* g_imageBuf = 0;
HDC             g_hMem = 0;
HBITMAP	        g_hBmp = 0;

class   DecodeThread :public Thread
{
public:
    FFVideoReader   _ffReader;
    HWND            _hWnd;
    bool            _exitFlag;
public:
    DecodeThread()
    {
        _ffReader.setup();
        _hWnd = 0;
        _exitFlag = false;
    }

    void    exitThread()
    {
        _exitFlag = true;
        join();
    }
    /**
    *   加载文件
    */
    virtual void    load(const char* fileName)
    {
        _ffReader.load(fileName);
    }
    /**
    *   线程执行函数
    */
    virtual bool    run()
    {
        while (!_exitFlag)
        {
            FrameInfor  infor;
            if (!_ffReader.readFrame(infor))
            {
                break;
            }

            BYTE* data = (BYTE*)infor._data;
            for (int i = 0; i < infor._dataSize; i += 3)
            {
                g_imageBuf[i + 0] = data[i + 2];
                g_imageBuf[i + 1] = data[i + 1];
                g_imageBuf[i + 2] = data[i + 0];
            }
            InvalidateRect(_hWnd, 0, 0);
        }

        return  true;
    }
};

DecodeThread    g_decode;

LRESULT CALLBACK    windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC         hdc;
        hdc = BeginPaint(hWnd, &ps);
        if (g_hMem)
        {
            BITMAPINFO  bmpInfor;
            GetObject(g_hBmp, sizeof(bmpInfor), &bmpInfor);
            BitBlt(hdc, 0, 0, bmpInfor.bmiHeader.biWidth, bmpInfor.bmiHeader.biHeight, g_hMem, 0, 0, SRCCOPY);
        }

        EndPaint(hWnd, &ps);
    }
    break;
    case WM_SIZE:
        break;
    case WM_CLOSE:
    case WM_DESTROY:
        g_decode.exitThread();
        PostQuitMessage(0);
        break;
    default:
        break;
    }

    return  DefWindowProc(hWnd, msg, wParam, lParam);
}

int     WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    //  1   注册窗口类
    ::WNDCLASSEXA winClass;
    winClass.lpszClassName = "FFVideoPlayer";
    winClass.cbSize = sizeof(::WNDCLASSEX);
    winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
    winClass.lpfnWndProc = windowProc;
    winClass.hInstance = hInstance;
    winClass.hIcon = 0;
    winClass.hIconSm = 0;
    winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    winClass.hbrBackground = (HBRUSH)(BLACK_BRUSH);
    winClass.lpszMenuName = NULL;
    winClass.cbClsExtra = 0;
    winClass.cbWndExtra = 0;
    RegisterClassExA(&winClass);

    //  2 创建窗口
    HWND    hWnd = CreateWindowExA(
        NULL,
        "FFVideoPlayer",
        "FFVideoPlayer",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        0,
        0,
        480,
        320,
        0,
        0,
        hInstance,
        0
        );

    UpdateWindow(hWnd);
    ShowWindow(hWnd, SW_SHOW);

    char    szPath[1024];
    char    szPathName[1024];

    getResourcePath(hInstance, szPath);
    sprintf(szPathName, "%sdata/11.flv", szPath);

    HDC     hDC = GetDC(hWnd);
    g_hMem = ::CreateCompatibleDC(hDC);

    g_decode._hWnd = hWnd;
    g_decode.load(szPathName);


    BITMAPINFO	bmpInfor;
    bmpInfor.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfor.bmiHeader.biWidth = g_decode._ffReader._screenW;
    bmpInfor.bmiHeader.biHeight = -g_decode._ffReader._screenH;
    bmpInfor.bmiHeader.biPlanes = 1;
    bmpInfor.bmiHeader.biBitCount = 24;
    bmpInfor.bmiHeader.biCompression = BI_RGB;
    bmpInfor.bmiHeader.biSizeImage = 0;
    bmpInfor.bmiHeader.biXPelsPerMeter = 0;
    bmpInfor.bmiHeader.biYPelsPerMeter = 0;
    bmpInfor.bmiHeader.biClrUsed = 0;
    bmpInfor.bmiHeader.biClrImportant = 0;

    g_hBmp = CreateDIBSection(hDC, &bmpInfor, DIB_RGB_COLORS, (void**)&g_imageBuf, 0, 0);
    SelectObject(g_hMem, g_hBmp);

    g_decode.start();

    MSG     msg = { 0 };
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return  0;
}

速率控制

#pragma once


extern "C"
{
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libswscale/swscale.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
}


struct  FrameInfor
{
    void*   _data;
    int     _dataSize;
    int     _width;
    int     _height;
    int64_t _pts;
    double  _timeBase;
    
};
class   FFVideoReader
{
public:
    AVFormatContext*_formatCtx;
    int             _videoIndex;
    AVCodecContext* _codecCtx;
    AVCodec*        _codec;
    AVFrame*        _frame;
    AVFrame*        _frameRGB;
    SwsContext*     _convertCtx;
public:
    int             _screenW;
    int             _screenH;

    int             _imageSize;
public:
    FFVideoReader()
    {
        _formatCtx  =   0;
        _videoIndex =   -1;
        _codecCtx   =   0;
        _codec      =   0;
        _frame      =   0;
        _frameRGB   =   0;
        _convertCtx =   0;
        _screenW    =   0;
        _screenH    =   0;
        
    }

    ~FFVideoReader()
    {
        sws_freeContext(_convertCtx);
        av_free(_frameRGB);
        av_free(_frame);
        avcodec_close(_codecCtx);
        avformat_close_input(&_formatCtx);
    }

    void    setup()
    {
        av_register_all();
        _formatCtx  =   avformat_alloc_context();
    }
    int     load(const char* filepath = "11.flv")
    {
        int     ret     =   0;

        //! 打开文件
        if (avformat_open_input(&_formatCtx, filepath, NULL, NULL) != 0) 
        {
            return -1;
        }
        //! 检测文件中是否存在数据流
        if (avformat_find_stream_info(_formatCtx, NULL) < 0)
        {
            return -1;
        }
        //! 获取视频流索引
        _videoIndex = -1;
        for (int i = 0; i < _formatCtx->nb_streams; i++)
        {
            if (_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
            {
                _videoIndex = i;
                break;
            }
        }
        /**
        *   没有视频流,则返回
        */
        if (_videoIndex == -1) 
        {
            return -1;
        }
        _codecCtx   =   _formatCtx->streams[_videoIndex]->codec;

        double dur  =   _formatCtx->duration/double(AV_TIME_BASE);
        _codec      =   avcodec_find_decoder(_codecCtx->codec_id);
        if (_codec == NULL)
        {
            return -1;
        }
        /**
        *   打开解码器
        */
        if (avcodec_open2(_codecCtx, _codec, NULL) < 0) 
        {
            return -1;
        }
        _frame      =   av_frame_alloc();
        _frameRGB   =   av_frame_alloc();

        _screenW    =   _codecCtx->width;
        _screenH    =   _codecCtx->height;

        _convertCtx =   sws_getContext(
                                    _codecCtx->width
                                    , _codecCtx->height
                                    , _codecCtx->pix_fmt
                                    , _codecCtx->width
                                    , _codecCtx->height
                                    , AV_PIX_FMT_RGB24
                                    , SWS_BICUBIC
                                    , NULL
                                    , NULL
                                    , NULL
                                    );

        int     numBytes    =   avpicture_get_size(AV_PIX_FMT_RGB24, _codecCtx->width,_codecCtx->height);
        uint8_t*buffer      =   (uint8_t *) av_malloc (numBytes * sizeof(uint8_t));
        avpicture_fill((AVPicture *)_frameRGB, buffer, AV_PIX_FMT_RGB24,_codecCtx->width, _codecCtx->height);
        _imageSize  =   numBytes;
        return  0;
    }

    bool    readFrame(FrameInfor& infor)
    {
        AVPacket packet;
        av_init_packet(&packet);
        for (;;) 
        {
            if (av_read_frame(_formatCtx, &packet)) 
            {
                av_free_packet(&packet);
                return false;
            }
            if (packet.stream_index != _videoIndex) 
            {
                continue;
            }
            int frame_finished = 0;

            int res = avcodec_decode_video2(_codecCtx, _frame, &frame_finished, &packet);

            if (frame_finished)
            {
                AVStream*   streams =   _formatCtx->streams[_videoIndex];
                double      tmbase  =   av_q2d(streams->time_base);
                int64_t     pts     =   _frame->pts;

                char        buf[128];
                sprintf(buf,"pts = %I64d     dts =  %I64d\n",packet.pts,packet.dts);
                int res = sws_scale(
                    _convertCtx
                    , (const uint8_t* const*)_frame->data
                    , _frame->linesize
                    , 0
                    , _codecCtx->height
                    , _frameRGB->data
                    , _frameRGB->linesize
                    );
                av_packet_unref(&packet);

                infor._data     =   _frameRGB->data[0];
                infor._dataSize =   _imageSize;
                infor._width    =   _screenW;
                infor._height   =   _screenH;
                infor._pts      =   _frame->pts;
                infor._timeBase =   av_q2d(streams->time_base);

                return  true;
            }
        }
        return  false;
    }
    void*   readFrame()
    {
        AVPacket packet;
        av_init_packet(&packet);
        for (;;) 
        {
            if (av_read_frame(_formatCtx, &packet)) 
            {
                av_free_packet(&packet);
                return 0;
            }
            if (packet.stream_index != _videoIndex) 
            {
                continue;
            }
            int frame_finished = 0;

            int res = avcodec_decode_video2(_codecCtx, _frame, &frame_finished, &packet);

            if (frame_finished)
            {
                AVStream*   streams =   _formatCtx->streams[_videoIndex];
                double      tmbase  =   av_q2d(streams->time_base);
                int64_t     pts     =   _frame->pts;

                char        buf[128];
                sprintf(buf,"pts = %I64d     dts =  %I64d\n",packet.pts,packet.dts);
                int res = sws_scale(
                    _convertCtx
                    , (const uint8_t* const*)_frame->data
                    , _frame->linesize
                    , 0
                    , _codecCtx->height
                    , _frameRGB->data
                    , _frameRGB->linesize
                    );
                av_packet_unref(&packet);

                return  _frameRGB->data[0];
            }
        }
        return  0;
    }
};
  • 时间:
#pragma once
#include <windows.h>
class Timestamp
{
public:
    Timestamp()
    {
        QueryPerformanceFrequency(&_frequency);
        QueryPerformanceCounter(&_startCount);
    }
    ~Timestamp()
    {}

    void    update()
    {
        QueryPerformanceCounter(&_startCount);
    }
    /**
    *   获取当前秒
    */
    double getElapsedSecond()
    {
        return  getElapsedTimeInMicroSec() * 0.000001;
    }
    /**
    *   获取毫秒
    */
    double getElapsedTimeInMilliSec()
    {
        return this->getElapsedTimeInMicroSec() * 0.001;
    }
    /**
    *   获取微妙
    */
    double getElapsedTimeInMicroSec()
    {
        LARGE_INTEGER endCount;
        QueryPerformanceCounter(&endCount);

        double  startTimeInMicroSec =   _startCount.QuadPart * (1000000.0 / _frequency.QuadPart);
        double  endTimeInMicroSec   =   endCount.QuadPart * (1000000.0 / _frequency.QuadPart);

        return  endTimeInMicroSec - startTimeInMicroSec;
    }
protected:
    LARGE_INTEGER   _frequency;
    LARGE_INTEGER   _startCount;
};
#include <windows.h>
#include <tchar.h>
#include "FFVideoReader.hpp"
#include "Thread.hpp"
#include "Timestamp.hpp"

void  getResourcePath(HINSTANCE hInstance,char pPath[1024])
{
    char    szPathName[1024];
    char    szDriver[64];
    char    szPath[1024];
    GetModuleFileNameA(hInstance,szPathName,sizeof(szPathName));
    _splitpath( szPathName, szDriver, szPath, 0, 0 );
    sprintf(pPath,"%s%s",szDriver,szPath);
}

class   DecodeThread :public Thread
{
public:
    FFVideoReader   _ffReader;
    HWND            _hWnd;
    BYTE*           _imageBuf;
    HDC             _hMem;
    HBITMAP	        _hBmp;

    bool            _exitFlag;
    Timestamp       _timestamp;
public:
    DecodeThread()
    {
        _exitFlag   =   false;
        _hWnd       =   0;
    }

    virtual void    setup(HWND hwnd,const char* fileName = "11.flv")
    {
        _hWnd   =   hwnd;
        _ffReader.setup();
        _ffReader.load(fileName);

        HDC     hDC     =   GetDC(hwnd);
        _hMem   =   ::CreateCompatibleDC(hDC);
        
        BITMAPINFO	bmpInfor;
        bmpInfor.bmiHeader.biSize			=	sizeof(BITMAPINFOHEADER);
        bmpInfor.bmiHeader.biWidth			=	_ffReader._screenW;
        bmpInfor.bmiHeader.biHeight			=	-_ffReader._screenH;
        bmpInfor.bmiHeader.biPlanes			=	1;
        bmpInfor.bmiHeader.biBitCount		=	24;
        bmpInfor.bmiHeader.biCompression	=	BI_RGB;
        bmpInfor.bmiHeader.biSizeImage		=	0;
        bmpInfor.bmiHeader.biXPelsPerMeter	=	0;
        bmpInfor.bmiHeader.biYPelsPerMeter	=	0;
        bmpInfor.bmiHeader.biClrUsed		=	0;
        bmpInfor.bmiHeader.biClrImportant	=	0;

        _hBmp    =	CreateDIBSection(hDC,&bmpInfor,DIB_RGB_COLORS,(void**)&_imageBuf,0,0);
        SelectObject(_hMem,_hBmp);
    }
    /**
    *   加载文件
    */
    virtual void    load(const char* fileName)
    {
        _ffReader.load(fileName);
    }

    virtual void    join()
    {
        _exitFlag   =   true;
        Thread::join();
    }
    /**
    *   线程执行函数
    */
    virtual bool    run()
    {
        _timestamp.update();
        while(!_exitFlag)
        {
            FrameInfor  infor;
            if (!_ffReader.readFrame(infor))
            {
                break;
            }
            double      tims    =   infor._pts * infor._timeBase * 1000;
            BYTE*   data    =   (BYTE*)infor._data;
            for (int i = 0 ;i < infor._dataSize; i += 3 )
            {
                _imageBuf[i + 0 ]   =   data[i + 2];
                _imageBuf[i + 1 ]   =   data[i + 1];
                _imageBuf[i + 2 ]   =   data[i + 0];
            }
            //! 这里需要通知窗口进行重绘制更新,显示更新数据
            InvalidateRect(_hWnd,0,0);
            
            double      elsped  =   _timestamp.getElapsedTimeInMilliSec();
            double      sleeps  =   (tims - elsped);
            if (sleeps > 1)
            {
                Sleep((DWORD)sleeps);
            }
        }

        return  true;
    }
};

DecodeThread    g_decode;

LRESULT CALLBACK    windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC         hdc;
            hdc = BeginPaint(hWnd, &ps);
            if (g_decode._hMem)
            {
                BITMAPINFO  bmpInfor;
                GetObject(g_decode._hBmp,sizeof(bmpInfor),&bmpInfor);
                BitBlt(hdc,0,0,bmpInfor.bmiHeader.biWidth,bmpInfor.bmiHeader.biHeight,g_decode._hMem,0,0,SRCCOPY);
            }

            EndPaint(hWnd, &ps);
        }
        break;
    case WM_SIZE:
        break;
    case WM_CLOSE:
    case WM_DESTROY:
        g_decode.join();
        PostQuitMessage(0);
        break;
    default:
        break;
    }

    return  DefWindowProc( hWnd, msg, wParam, lParam );
}

int     WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
    //  1   注册窗口类
    ::WNDCLASSEXA winClass;
    winClass.lpszClassName  =   "FFVideoPlayer";
    winClass.cbSize         =   sizeof(::WNDCLASSEX);
    winClass.style          =   CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
    winClass.lpfnWndProc    =   windowProc;
    winClass.hInstance      =   hInstance;
    winClass.hIcon	        =   0;
    winClass.hIconSm	    =   0;
    winClass.hCursor        =   LoadCursor(NULL, IDC_ARROW);
    winClass.hbrBackground  =   (HBRUSH)(BLACK_BRUSH);
    winClass.lpszMenuName   =   NULL;
    winClass.cbClsExtra     =   0;
    winClass.cbWndExtra     =   0;
    RegisterClassExA(&winClass);

    //  2 创建窗口
    HWND    hWnd   =   CreateWindowExA(
        NULL,
        "FFVideoPlayer",
        "FFVideoPlayer",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        0,
        0,
        480,
        320, 
        0, 
        0,
        hInstance, 
        0
        );

    UpdateWindow( hWnd );
    ShowWindow(hWnd,SW_SHOW);

    char    szPath[1024];
    char    szPathName[1024];

    getResourcePath(hInstance,szPath);
    sprintf(szPathName,"%sdata/11.flv",szPath);

    g_decode.setup(hWnd,szPathName);
    g_decode.start();

    MSG     msg =   {0};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    return  0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值