FFmpeg多線程畫中畫視頻實(shí)現(xiàn)--Apple的學(xué)習(xí)筆記

之前已經(jīng)完成了基于opencv的ffmpeg視頻顯示框架。覺得比較好的就是畫中畫。所以先做一個(gè)原型作為入門。

設(shè)計(jì)方案

要實(shí)現(xiàn)一種功能,方法多種多樣,基于我現(xiàn)在的目的是學(xué)習(xí)FFmpeg的應(yīng)用。所以呢參考了網(wǎng)上的畫中畫實(shí)現(xiàn)方式。
我要做一個(gè)多線程通過線程A完成一幀大屏幀解碼后發(fā)送消息到線程B去做一幀小屏幀解碼,小屏幀解碼后再發(fā)一幀消息同步大屏幀,然后通過opencv的ROI來合并大屏和小屏幀。

遇到問題

  1. 如何放大縮小視頻,ffmpeg的sws_getContext雖小視頻后,顯示有一部分黑色框。我暫時(shí)無法用ffmpeg最小視頻,所以就用opencv的resize還是來縮小。
  2. opencv的Copyto函數(shù)無效果。最后網(wǎng)上查到,Copyto的大小需要和img大小一致才能copy成功。

WIN32多線程框架驗(yàn)證

#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;
//線程函數(shù)
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;
        
}

//線程函數(shù)
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傳遞參數(shù)
    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); // 等待,直到線程被激發(fā)
    CloseHandle(hThread);
    CloseHandle(hThread1);
    while (1);
    return 0;

}

關(guān)鍵合并函數(shù)

此框架驗(yàn)證消息收發(fā)正常,返回把fun和fun1替換成功之前的FFmpeg顯示函數(shù),在對(duì)應(yīng)位置添加發(fā)送和接收消息即可。

                ////轉(zhuǎn)換圖像格式,將解壓出來的YUV420P的圖像轉(zhuǎn)換為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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容