Mac OS使用FFmpeg添加視頻濾鏡

一.概述

一般來說舶胀,給視頻添加濾鏡有兩種方式祝旷,一種是錄制的時候添加濾鏡,如基于Open GL的GPUImage竖哩。還有一種是編碼的時候添加濾鏡哭廉,如FFmpeg。本文將使用FFmpeg框架中的AVFilter給視頻添加濾鏡相叁。

本文使用FFmpeg 4.2遵绰,Mac OS系統(tǒng)

二.初始化濾鏡

1.獲取濾鏡處理源:獲得源及濾鏡處理的Sink濾鏡,同時申請輸入與輸出的濾鏡結構AVFilterInOut增淹。

const AVFilter *buffersrc  = avfilter_get_by_name("buffer");
const AVFilter *buffersink = avfilter_get_by_name("buffersink");
        
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs  = avfilter_inout_alloc();

2.處理AVFilterGraph:存儲AVFilter的in和out描述信息椿访。

filter_graph = avfilter_graph_alloc();

3.創(chuàng)建AVFilterContext

       snprintf(args, sizeof(args),
                 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
                 1280,720,AV_PIX_FMT_YUV420P,
                 1, 25,1,1);
        
        ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
                                           args, NULL, filter_graph);
        if (ret < 0) {
            printf("Cannot create buffer source\n");
            return;
        }


        /* buffer video sink: to terminate the filter chain. */
        buffersink_params = av_buffersink_params_alloc();
        buffersink_params->pixel_fmts = pix_fmts;
        ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
                                           NULL, buffersink_params, filter_graph);
        if (ret < 0) {
            printf("ret == %s\n", av_err2str(ret));
            return;
        }

4.設置其他參數(shù)

ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
    av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
    return;
}

5.建立濾鏡解析器

    NSString *desc = @"[in]geq=r='X/W*r(X,Y)':g='(1-X/W)*g(X,Y)':b='(H-Y)/H*b(X,Y)',drawtext=fontfile=/Library/Fonts/Arial Unicode.ttf:x=10:y=10:fontcolor=white:fontsize=40:text='版權為愛奇藝官方所有,請勿應用于商業(yè)活動虑润。'[text];movie=[path]aqylog.imageset/aqylog.png[wm];[text][wm]overlay=W-w-40:H-h-40 ,scale=1280:720";
const char *filter_descr = [desc cStringUsingEncoding:NSUTF8StringEncoding];
       /* Endpoints for the filter graph. */
        outputs->name       = av_strdup("in");
        outputs->filter_ctx = buffersrc_ctx;
        outputs->pad_idx    = 0;
        outputs->next       = NULL;
        
        inputs->name       = av_strdup("out");
        inputs->filter_ctx = buffersink_ctx;
        inputs->pad_idx    = 0;
        inputs->next       = NULL;
        
        if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr,
                                            &inputs, &outputs, NULL)) < 0){
            printf("Error avfilter_graph_parse_ptr \n");
            return;
        }
            
        
        if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0){
            printf("Error avfilter_graph_config \n");
            return;
        }

6.初始化一個用于添加濾鏡后輸出的AVFrame

        frame_out = av_frame_alloc();
        frame_out->width = pCodecContext->width;
        frame_out->height = pCodecContext->height;
        frame_out->format = pCodecContext->pix_fmt;
        ret = av_frame_get_buffer(frame_out, 0);
        if (ret < 0) {
            printf("ret == %s\n", av_err2str(ret));
        }
        
        avfilter_inout_free(&inputs);
        avfilter_inout_free(&outputs);
        av_free(buffersink_params);

三.編碼時添加濾鏡

上文已經(jīng)介紹如何生成原始的AVFrame成玫,添加濾鏡后生成新的AVFrame,送入編碼器編碼拳喻。

            int ret;
            if (kUseAVFilter) {
                frame_out->pts = frameCount;
                frame_out->width = 1280;
                frame_out->height = 720;
                frame_out->format = AV_PIX_FMT_YUV420P;
                frame_out->linesize[0] = 1280;
                frame_out->linesize[1] = 640;
                frame_out->linesize[2] = 640;

                ret = av_buffersrc_add_frame(buffersrc_ctx, pFrame);
                if (ret < 0) {
                    printf("av_buffersrc_add_frame == %s\n", av_err2str(ret));
                    return;
                }
                
                ret = av_buffersink_get_frame(buffersink_ctx, frame_out);
                if (ret) {
                    printf("av_buffersink_get_frame == %s\n", av_err2str(ret));
                    return;
                }
                
                ret = avcodec_send_frame(pCodecContext, frame_out);
            }else{
                ret = avcodec_send_frame(pCodecContext, pFrame);
            }

四.濾鏡的效果

選擇濾鏡在于上文的filter_descr設置哭当,由3個濾鏡組成:
1.geq濾鏡:實現(xiàn)冷暖分割效果

geq=r='X/W*r(X,Y)':g='(1-X/W)*g(X,Y)':b='(H-Y)/H*b(X,Y)'

2.drawtext文字濾鏡:在視頻上添加文字,需要注意的是添加中文要選擇支持中文的.ttf文件冗澈,否則會顯示方框钦勘。

drawtext=fontfile=/Library/Fonts/Arial Unicode.ttf:x=10:y=10:fontcolor=white:fontsize=40:text='版權為愛奇藝官方所有,請勿應用于商業(yè)活動渗柿。'[text]

3.movie濾鏡个盆,添加圖片logo,WH是視頻的整體寬高朵栖,wh是圖片的寬高颊亮。

movie=[path]aqylog.imageset/aqylog.png[wm];[text][wm]overlay=W-w-40:H-h-40

效果如下:


原圖

添加濾鏡效果圖

FFmpeg視頻濾鏡目前大概有近200種,常用的有:
淡入淡出的fade濾鏡陨溅,消除logo的delogo濾鏡终惑,增加亮度的brightness濾鏡等等,具體詳見官方文檔门扇。

FFmpeg-Fliters官方文檔

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雹有,一起剝皮案震驚了整個濱河市偿渡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霸奕,老刑警劉巖溜宽,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異质帅,居然都是意外死亡适揉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進店門煤惩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫉嘀,“玉大人,你說我怎么就攤上這事魄揉〖粑辏” “怎么了?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵洛退,是天一觀的道長瓣俯。 經(jīng)常有香客問我,道長不狮,這世上最難降的妖魔是什么降铸? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮摇零,結果婚禮上推掸,老公的妹妹穿的比我還像新娘。我一直安慰自己驻仅,他們只是感情好谅畅,可當我...
    茶點故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著噪服,像睡著了一般毡泻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粘优,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天仇味,我揣著相機與錄音,去河邊找鬼雹顺。 笑死丹墨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的嬉愧。 我是一名探鬼主播贩挣,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了王财?” 一聲冷哼從身側響起卵迂,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绒净,沒想到半個月后见咒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡挂疆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年论颅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囱嫩。...
    茶點故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖漏设,靈堂內(nèi)的尸體忽然破棺而出墨闲,到底是詐尸還是另有隱情,我是刑警寧澤郑口,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布鸳碧,位于F島的核電站,受9級特大地震影響犬性,放射性物質(zhì)發(fā)生泄漏瞻离。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一乒裆、第九天 我趴在偏房一處隱蔽的房頂上張望套利。 院中可真熱鬧,春花似錦鹤耍、人聲如沸肉迫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喊衫。三九已至,卻和暖如春杆怕,著一層夾襖步出監(jiān)牢的瞬間族购,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工陵珍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寝杖,地道東北人。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓撑教,卻偏偏與公主長得像朝墩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容