zoukankan      html  css  js  c++  java
  • EasyPlayerPro Windows播放器本地快照抓拍截图功能实现方法

    背景描述

    作为一个播放器,截图功能必不可少; 下面主要记录一下截图功能的实现;

    EasyPlayerPro

    实现流程

    • 将解码后的帧进行格式转换(目标格式为RGB24);

    • 采用独立的线程进行截图处理;

    • 截图可保存为BMP或JPG两种格式;

    EasyPlayerPro

    代码实现

    #define _WIDTHBYTES(c)  ((c+31)/32*4)   // c = width * bpp
    int Snapshot2File(RENDER_FORMAT renderFormat, SNAPSHOT_IMAGE_T *pSnapshot, char *pbuf)
    {
    PBYTE   pDest = NULL, pDest16 = NULL;
    INT     nBpp;
    DWORD   dwW, dwH, dwWB;
    
    int     ret = 0;
    
    int image_format = pSnapshot->imageFormat;
    
    
    if (renderFormat == RENDER_FORMAT_YUY2)             nBpp    =   16;
    else if (renderFormat == RENDER_FORMAT_UYVY)        nBpp    =   16;
    else if (renderFormat == RENDER_FORMAT_X8R8G8B8)    nBpp    =   32;     //ok
    else if (renderFormat == RENDER_FORMAT_A8R8G8B8)    nBpp    =   32;     //ok
    else if (renderFormat == RENDER_FORMAT_RGB565)      nBpp    =   16;     //ok
    else if (renderFormat == RENDER_FORMAT_RGB555)      nBpp    =   16;     //ok
    else if (renderFormat == RENDER_FORMAT_RGB24_GDI)   nBpp    =   24;
    else    return -1;      //格式错误
    
    dwW  = pSnapshot->width;
    dwH  = pSnapshot->height;
    dwWB = _WIDTHBYTES( dwW * nBpp );
    
    if (image_format == 0x00)
    {
        //BMP
        int iFilenameLen = (int)strlen(pSnapshot->filename);
    
        if ( (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "bmp", 3)) &&
            (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "BMP", 3)) &&
            (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "Bmp", 3)) )
        {
            if (pSnapshot->filename[iFilenameLen-4] == '.')
            {
                for (int i=iFilenameLen-1; i>0; i--)
                {
                    if (pSnapshot->filename[i] == '.')
                    {
                        pSnapshot->filename[i] = '';
                        break;
                    }
                    else
                    {
                        pSnapshot->filename[i] = '';
                    }
                }
            }
            strcat(pSnapshot->filename, ".bmp");
        }
    
        HANDLE hFile = CreateFile( pSnapshot->filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,       CREATE_ALWAYS,  FILE_ATTRIBUTE_NORMAL,  NULL );
        if( hFile == INVALID_HANDLE_VALUE ) return E_HANDLE;
    
        // SaveFile to BMP
        BITMAPFILEHEADER bfh = {0};
        bfh.bfType      = 0x4D42;
        bfh.bfSize      = 0;
        bfh.bfReserved1 = 0;
        bfh.bfReserved2 = 0;
        bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
        if( nBpp == 16 ) {
            bfh.bfOffBits += sizeof(RGBQUAD) * 3;
        }
        else
            if( nBpp == 24 ) {
                bfh.bfOffBits += sizeof(RGBQUAD) * 1;
            }
            else
                if( nBpp == 32 ) {
                    bfh.bfOffBits += sizeof(RGBQUAD) * 1;
                }
                DWORD dwWriteLength = sizeof(BITMAPFILEHEADER);
                DWORD dwWrittenLength = 0;
                WriteFile( hFile, (PVOID)&bfh, dwWriteLength, &dwWrittenLength, NULL );
    
                BITMAPINFOHEADER    bih = {0};
                bih.biSize      = sizeof(BITMAPINFOHEADER);
                bih.biWidth     = dwW;
                bih.biHeight    = -(INT)dwH;
                bih.biPlanes    = 1;
                bih.biBitCount  = nBpp;
                bih.biCompression   = (nBpp == 16) ? BI_BITFIELDS : BI_RGB;
                bih.biSizeImage     = dwWB * pSnapshot->height;
                bih.biXPelsPerMeter = 0;
                bih.biYPelsPerMeter = 0;
                bih.biClrUsed       = 0;
                bih.biClrImportant  = 0;
    
                dwWriteLength = sizeof(BITMAPINFOHEADER);
                WriteFile( hFile, (PVOID)&bih, dwWriteLength, &dwWrittenLength, NULL );
    
                if( nBpp == 16 ) {
    
                    DWORD argbQuad[3] = {0};
                    if (renderFormat == RENDER_FORMAT_RGB565)
                    {
                        argbQuad[0] = 0x00F800;     // Red mask
                        argbQuad[1] = 0x0007E0;     // Green mask
                        argbQuad[2] = 0x00001F;     // Blue mask
                    }
                    else
                    {
                        argbQuad[0] = 0x007C00;     // Red mask
                        argbQuad[1] = 0x0003E0;     // Green mask
                        argbQuad[2] = 0x00001F;     // Blue mask
                    }
                    dwWriteLength = sizeof(argbQuad);
                    WriteFile( hFile, (PVOID)&argbQuad[0], dwWriteLength, &dwWrittenLength, NULL );
                }
                else
                    if( nBpp == 24 ) {
                        DWORD rgbQuad = 0;
                        dwWriteLength = sizeof(rgbQuad);
                        WriteFile( hFile, (PVOID)&rgbQuad, dwWriteLength, &dwWrittenLength, NULL );
                    }
                    else if( nBpp == 32 ) {
                        DWORD rgbQuad = 0;
                        dwWriteLength = sizeof(rgbQuad);
                        WriteFile( hFile, (PVOID)&rgbQuad, dwWriteLength, &dwWrittenLength, NULL );
                    }
    
                    dwWriteLength = dwWB * pSnapshot->height;
                    WriteFile( hFile, (PVOID)pbuf, dwWriteLength, &dwWrittenLength, NULL );
                    CloseHandle( hFile );
    
        if (dwWrittenLength < 1)
        {
            DeleteFile(pSnapshot->filename);
        }
    }
    else if (image_format == 0x01)
    {
        //JPG
        int iFilenameLen = (int)strlen(pSnapshot->filename);
    
        if ( (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "jpg", 3)) &&
            (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "JPG", 3)) &&
            (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "Jpg", 3)) )
        {
            if (pSnapshot->filename[iFilenameLen-4] == '.')
            {
                for (int i=iFilenameLen-1; i>0; i--)
                {
                    if (pSnapshot->filename[i] == '.')
                    {
                        pSnapshot->filename[i] = '';
                        break;
                    }
                    else
                    {
                        pSnapshot->filename[i] = '';
                    }
                }
            }
            strcat(pSnapshot->filename, ".jpg");
        }
    
        BOOL bres = TRUE;
        IJLERR jerr;
        DWORD dibPadBytes;
        JPEG_CORE_PROPERTIES jcprops;
    
        __try
        {
            jerr = ijlInit(&jcprops);
    
            if (IJL_OK != jerr)
            {
                bres = FALSE;
                __leave;
            }
    
    
            dibPadBytes = IJL_DIB_PAD_BYTES(dwW, 3);
    
            jcprops.DIBWidth = dwW;
            jcprops.DIBHeight = dwH;
            jcprops.DIBBytes = (unsigned char*)pbuf;//reinterpret_cast<BYTE *>(&pbi->bmiHeader) + sizeof(BITMAPINFOHEADER);
    
            jcprops.DIBPadBytes = dibPadBytes;
            jcprops.DIBChannels = 3;
            jcprops.DIBColor = IJL_BGR;
    
            jcprops.JPGFile = const_cast<LPSTR>(pSnapshot->filename);
    
            jcprops.JPGWidth = dwW;
            jcprops.JPGHeight = dwH;
    
            jcprops.JPGChannels = 3;
            jcprops.JPGColor = IJL_YCBCR;
            jcprops.JPGSubsampling = IJL_411;
            jcprops.jquality = 95;
    
            jerr = ijlWrite(&jcprops, IJL_JFILE_WRITEWHOLEIMAGE);
    
            if (IJL_OK != jerr)
            {
                if (IJL_FILE_ERROR == jerr)
                {
                }
                ret = jerr;
                bres = FALSE;
    
                if (ret == -23)
                {
                    DeleteFile(pSnapshot->filename);
                }
            }
        }
    
        __finally
        {
            ijlFree(&jcprops);
        }
    
    }
    
    if (NULL != pDest)
    {
        delete []pDest;
        pDest = NULL;
    }
    
    return ret;
    }
    

    关于EasyPlayerPro

    EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP、RTMP、HTTP、HLS、UDP、RTP、File等多种流媒体协议播放、支持本地文件播放,支持本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种功能特性,核心基于ffmpeg,稳定、高效、可靠、可控,支持Windows、Android、iOS三个平台,目前在多家教育、安防、行业型公司,都得到的应用,广受好评!

    EasyPlayerPro:https://github.com/EasyDSS/EasyPlayerPro

    点击链接加入群【EasyPlayer & EasyPlayerPro】:544917793

    获取更多信息

    邮件:support@easydarwin.org

    EasyDarwin开源流媒体服务器:www.EasyDarwin.org

    EasyDSS商用流媒体解决方案:www.EasyDSS.com

    EasyNVR无插件直播方案:www.EasyNVR.com

    Copyright © EasyDarwin Team 2012-2017

    EasyDarwin

  • 相关阅读:
    三种负载均衡 Nginx、Dubbo、Ribbon 区别
    Docker基础学习
    主从复制报错2061:Authentication plugin 'caching_sha2_password' reported error:Authentication require secure connection
    LRU、LFU算法区别
    CAP理论原理
    Mysql安装服务到Window服务列表
    从零开始掌握 HAProxy 负载均衡器,详细!!
    一举拿下Nginx
    Nginx 负载均衡配置误区
    Linux自动化技巧
  • 原文地址:https://www.cnblogs.com/babosa/p/9217704.html
Copyright © 2011-2022 走看看