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

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

设计方案

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

遇到问题

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

WIN32多线程框架验证

#include 
#include 

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 " <

关键合并函数

此框架验证消息收发正常,返回把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的学习笔记)