美文网首页
FFmpeg多线程画中画视频实现--Apple的学习笔记

FFmpeg多线程画中画视频实现--Apple的学习笔记

作者: applecai | 来源:发表于2020-06-26 10:38 被阅读0次

    之前已经完成了基于opencv的ffmpeg视频显示框架。觉得比较好的就是画中画。所以先做一个原型作为入门。

    设计方案

    要实现一种功能,方法多种多样,基于我现在的目的是学习FFmpeg的应用。所以呢参考了网上的画中画实现方式。
    我要做一个多线程通过线程A完成一帧大屏帧解码后发送消息到线程B去做一帧小屏帧解码,小屏帧解码后再发一帧消息同步大屏帧,然后通过opencv的ROI来合并大屏和小屏帧。

    遇到问题

    1. 如何放大缩小视频,ffmpeg的sws_getContext虽小视频后,显示有一部分黑色框。我暂时无法用ffmpeg最小视频,所以就用opencv的resize还是来缩小。
    2. opencv的Copyto函数无效果。最后网上查到,Copyto的大小需要和img大小一致才能copy成功。

    WIN32多线程框架验证

    #include <iostream>
    #include <windows.h>
    
    using namespace std;
    DWORD  dwThreadID;
    DWORD  dwThreadID1;
    #define WM_MY_MESSAGE  (WM_USER+1)
    #define WM_MY_MESSAGE_MERGE  (WM_USER+2)
    MSG msg;
    //线程函数
    DWORD  WINAPI  Fun(LPVOID lpParameter)
    {
        char *str = (char*)lpParameter;
        int ret = 0;
        for (int i = 0; i < 10; i++)
        {
            cout << "Displaying " << str << endl;
            ret = PostThreadMessage(dwThreadID1, WM_MY_MESSAGE, 0, 0);
            if (GetMessage(&msg, NULL, 0, 0))
            {
                if (msg.message == WM_MY_MESSAGE_MERGE)
                {
                    cout << "Merge " <<endl;
                }
            }
        }
        return 0;
            
    }
    
    //线程函数
    DWORD  WINAPI  Fun1(LPVOID lpParameter)
    {
        char *str = (char*)lpParameter;
            for (int i = 0; i < 10; i++)
            {
                if (GetMessage(&msg, NULL, 0, 0))
                {
                    if (msg.message == WM_MY_MESSAGE)
                    {
                        cout << "Displaying " << str << endl;
                    }
                    PostThreadMessage(dwThreadID, WM_MY_MESSAGE_MERGE, 0, 0);
                }
            }
            return 0;
    }
    
    int main()
    {
        //使用struct传递参数
        char Ptr[] = "123";
        char Ptr1[] = "456";
        HANDLE hThread1 = CreateThread(NULL, 0, Fun1, Ptr1, 0, &dwThreadID1);
        WaitForSingleObject(&dwThreadID, 25);
        HANDLE hThread = CreateThread(NULL, 0, Fun, Ptr, 0, &dwThreadID);
        //WaitForSingleObject(hThread, INFINITE); // 等待,直到线程被激发
        CloseHandle(hThread);
        CloseHandle(hThread1);
        while (1);
        return 0;
    
    }
    

    关键合并函数

    此框架验证消息收发正常,返回把fun和fun1替换成功之前的FFmpeg显示函数,在对应位置添加发送和接收消息即可。

                    ////转换图像格式,将解压出来的YUV420P的图像转换为BRG24的图像
                    if (GetMessage(&msg, NULL, 0, 0))
                    {
                        if (msg.message == WM_MY_MESSAGE_MERGE)
                        {
                            cv::Mat frameImage(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3, cv::Scalar(0));
                            //std::cout << "pCodecCtx->width=" << pCodecCtx->width << std::endl;
                            //cv::Mat imageROI = frameImage(cv::Rect(0, 0, 480, 360));
                            frameImage.data = pFrameRGB->data[0];
                            cv::Mat OutImg;
                            cv::Mat imageROI;
                            cv::Mat frameTV(cv::Size(w2, h2), CV_8UC3, cv::Scalar(0));
                            //std::cout << "w2=" << w2 << std::endl;
                            frameTV.data = (uchar *)msg.wParam;
                            if (msg.wParam != NULL)
                            {
                                cv::resize(frameTV, OutImg, cv::Size(480, 360), 0, 0, cv::INTER_LINEAR);
                                cv::Mat imageROI = frameImage(cv::Rect(0, 0, OutImg.cols, OutImg.rows));
                                OutImg.copyTo(imageROI);
                                //OutImg.release();
                            }
                            if (pFrameRGB->data[0] != NULL)
                            {
                                cv::namedWindow("Video", CV_WINDOW_AUTOSIZE);
                                cv::imshow("Video", frameImage);
                                cv::waitKey(33);
                            }
                            frameImage.release();
                            imageROI.release();
                            frameTV.release();
                            OutImg.release();
                        }
                    }
    

    画中画效果

    image.png

    相关文章

      网友评论

          本文标题:FFmpeg多线程画中画视频实现--Apple的学习笔记

          本文链接:https://www.haomeiwen.com/subject/csbyfktx.html