FFmpeg常用API與示例(四)——過濾器實戰

1.filter

在多媒體處理中,filter 的意思是被編碼到輸出文件之前用來修改輸入文件內容的一個軟件工具。如:視頻翻轉,旋轉,縮放等。

語法:[input_link_label1]… filter_name=parameters [output_link_label1]…

1、視頻過濾器 -vf

如 input.mp4 視頻按順時針方向旋轉 90 度

ffplay -i input.mp4 -vf transpose=1

如 input.mp4 視頻水平翻轉(左右翻轉)

ffplay -i input.mp4 -vf hflip

2、音頻過濾器 -af

實現慢速播放,聲音速度是原始速度的 50%

offplay input.mp3 -af atempo=0.5

過濾器鏈(Filterchain)

Filterchain = 逗號分隔的一組 filter

語法:“filter1,filter2,filter3,…filterN-2,filterN-1,filterN”

順時針旋轉 90 度并水平翻轉

ffplay -i input.mp4 -vf transpose=1,hflip

過濾器圖(Filtergraph)

第一步: 源視頻寬度擴大兩倍。

ffmpeg -i jidu.mp4 -t 10 -vf pad=2*iw output.mp4

第二步:源視頻水平翻轉

ffmpeg -i jidu.mp4 -t 10 -vf hflip output2.mp4

第三步:水平翻轉視頻覆蓋 output.mp4

ffmpeg -i output.mp4 -i output2.mp4 -filter_complex overlay=w compare.mp4

是不是很復雜?

用帶有鏈接標記的過濾器圖(Filtergraph)只需一條命令

基本語法

Filtergraph = 分號分隔的一組 filterchain

“filterchain1;filterchain2;…filterchainN-1;filterchainN”

Filtergraph 的分類

1、簡單(simple) 一對一

2、復雜(complex)多對一, 多對多

過濾器圖處理流程:

在這里插入圖片描述

對于剛才用三步處理的方式,用過濾器圖可以這樣做:

ffplay -f lavfi -i testsrc -vf split[a][b];[a]pad=2*iw[1];[b]hflip[2];[1][2]overlay=w

F1: split 過濾器創建兩個輸入文件的拷貝并標記為[a],[b]

F2: [a]作為 pad 過濾器的輸入,pad 過濾器產生 2 倍寬度并輸出到[1].

F3: [b]作為 hflip 過濾器的輸入,vflip 過濾器水平翻轉視頻并輸出到[2].

F4: 用 overlay 過濾器把 [2]覆蓋到[1]的旁邊.

filter 涉及的結構體,主要包括:

  • FilterGraph, AVFilterGraph

  • InputFilter, InputStream, OutputFilter, OutputStream

  • AVFilter, AVFilterContext

  • AVFilterLink

  • AVFilterPad;

2.DirectShow

DirectShow(簡稱 DShow) 是一個 Windows 平臺上的流媒體框架,提供了高質量的多媒體流采集和回放功能。它支持多種多樣的媒體文件格式,包括 ASF、MPEG、AVI、MP3和 WAV 文件,同時支持使 動或早期的 VFW 驅動來進行多媒體流的采集。

DirectShow 大大簡化了媒體回放、格式轉換和采集工作。但與此同時,它也為用戶自定義的解決方案提供了底層流控制框架,從而使用戶可以自行創建支持新的文件格式或其他用戶的 DirectShow 組件。

DirectShow 是基于**組件對象模型(COM)**的,因此當你編寫 DirectShow 應用程序時,你必須具備 COM 客戶端程序編寫的知識。對于大部分的應用程序,你不需要實現自己的COM 對象,DirectShow 提供了大部分你需要的 DirectShow 組件,但是假如你需要編寫自己的 DirectShow 組件來進行擴充,那么你必須編寫實現 COM 對象。

使用 DirectShow 編寫的典型應用程序包括:DVD 播放器、視頻編輯程序、AVI 到 ASF轉換器、 MP3 播放器和數字視頻采集應用。

在這里插入圖片描述

DirectShow 的架構如下圖所示:

在這里插入圖片描述

/*** @file* API example for decoding and filtering* @example filtering_video.c*/#define _XOPEN_SOURCE 600 /* for usleep */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>const char *filter_descr = "scale=640:480,hflip";
/* other way:scale=78:24 [scl]; [scl] transpose=cclock // assumes "[in]" and "[out]" to be input output pads respectively*/static AVFormatContext *fmt_ctx;
static AVCodecContext *dec_ctx;
AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph;
static int video_stream_index = -1;
static int64_t last_pts = AV_NOPTS_VALUE;static int open_input_file(const char *filename)
{int ret;AVCodec *dec;if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");return ret;}if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");return ret;}/* select the video stream */ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n");return ret;}video_stream_index = ret;/* create decoding context */dec_ctx = avcodec_alloc_context3(dec);if (!dec_ctx)return AVERROR(ENOMEM);avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[video_stream_index]->codecpar);/* init the video decoder */if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n");return ret;}return 0;
}static int init_filters(const char *filters_descr)
{char args[512];int ret = 0;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();AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base;enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };filter_graph = avfilter_graph_alloc();if (!outputs || !inputs || !filter_graph) {ret = AVERROR(ENOMEM);goto end;}/* buffer video source: the decoded frames from the decoder will be inserted here. */snprintf(args, sizeof(args),"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,time_base.num, time_base.den,dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den);ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",args, NULL, filter_graph);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");goto end;}/* buffer video sink: to terminate the filter chain. */ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",NULL, NULL, filter_graph);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");goto end;}/** Set the endpoints for the filter graph. The filter_graph will* be linked to the graph described by filters_descr.*//** The buffer source output must be connected to the input pad of* the first filter described by filters_descr; since the first* filter input label is not specified, it is set to "in" by* default.*/outputs->name       = av_strdup("in");outputs->filter_ctx = buffersrc_ctx;outputs->pad_idx    = 0;outputs->next       = NULL;/** The buffer sink input must be connected to the output pad of* the last filter described by filters_descr; since the last* filter output label is not specified, it is set to "out" by* default.*/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, filters_descr,&inputs, &outputs, NULL)) < 0)goto end;if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)goto end;end:avfilter_inout_free(&inputs);avfilter_inout_free(&outputs);return ret;
}/// 將yuv幀寫入文件:yuv420p格式
FILE * g__file_fd;
static void write_frame(const AVFrame *frame)
{static int printf_flag = 0;if(!printf_flag){printf_flag = 1;printf("frame widht=%d,frame height=%d\n",frame->width,frame->height);if(frame->format==AV_PIX_FMT_YUV420P){printf("format is yuv420p\n");}else{printf("formet is = %d \n",frame->format);}}fwrite(frame->data[0],1,frame->width*frame->height,g__file_fd);fwrite(frame->data[1],1,frame->width/2*frame->height/2,g__file_fd);fwrite(frame->data[2],1,frame->width/2*frame->height/2,g__file_fd);
}int main(int argc, char **argv)
{int ret;AVPacket packet;AVFrame *frame;AVFrame *filt_frame;if (argc != 2) {fprintf(stderr, "Usage: %s file\n", argv[0]);exit(1);}g__file_fd = fopen("yuv888.yuv", "w");frame = av_frame_alloc();filt_frame = av_frame_alloc();if (!frame || !filt_frame) {perror("Could not allocate frame");exit(1);}if ((ret = open_input_file(argv[1])) < 0)goto end;if ((ret = init_filters(filter_descr)) < 0)goto end;/* read all packets */while (1) {if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)break;if (packet.stream_index == video_stream_index) {ret = avcodec_send_packet(dec_ctx, &packet);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");break;}while (ret >= 0) {ret = avcodec_receive_frame(dec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {break;} else if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");goto end;}frame->pts = frame->best_effort_timestamp;/* push the decoded frame into the filtergraph */if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");break;}/* pull filtered frames from the filtergraph */while (1) {ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)break;if (ret < 0)goto end;write_frame(filt_frame);av_frame_unref(filt_frame);}av_frame_unref(frame);}}av_packet_unref(&packet);}
end:avfilter_graph_free(&filter_graph);avcodec_free_context(&dec_ctx);avformat_close_input(&fmt_ctx);av_frame_free(&frame);av_frame_free(&filt_frame);fclose(g__file_fd);if (ret < 0 && ret != AVERROR_EOF) {fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));exit(1);}exit(0);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10339.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10339.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10339.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++中調用python函數(VS2017+WIN10+Anaconda虛擬環境)

1.利用VS創建C空項目 step1 文件——新建——項目 step2 Visual C—— Windows桌面——Windows桌面向導 step3 選擇空項目 step4 源文件——新建項——添加 step5 Visual C——C文件&#xff08;.cpp&#xff09; 2.配置環境 Step1. 更換成Release與X64 Step2. 打開項目屬性&…

文本提取新技能:學會按行數批量提取,輕松應對各種需求

在數字化時代&#xff0c;文本處理成為我們日常生活和工作中不可或缺的一部分。無論是從網頁、文檔還是數據庫中提取信息&#xff0c;文本提取技能都顯得尤為重要。而按行數批量提取文本內容&#xff0c;更是文本處理中的一項高效且實用的技能。本文將介紹辦公提效工具如何按行…

在Spring Boot應用安裝SSL證書

目錄 前提條件 步驟一&#xff1a;下載SSL證書 步驟二&#xff1a;在Spring Boot安裝SSL證書 步驟三&#xff1a;驗證SSL證書是否安裝成功 前提條件 已通過數字證書管理服務控制臺簽發證書SSL證書綁定的域名已完成DNS解析&#xff0c;即您的域名與主機IP地址相互映射已在W…

ASP.NET學生信息管理系統

摘 要 本文介紹了在ASP.net環境下采用“自上而下地總體規劃&#xff0c;自下而上地應用開發”的策略開發一個管理信息系統的過程。通過分析某一學校學生管理的不足&#xff0c;創建了一套行之有效的計算機管理學生的方案。文章介紹了學生管理信息系統的系統分析部分&#xff0c…

微信投票源碼系統至尊版 吸粉變現功能二合一

源碼簡介 微信投票系統在營銷和社交互動中發揮著多方面的作用&#xff0c;它能夠提升用戶的參與度和品牌曝光度&#xff0c;還是一種有效的數據收集、營銷推廣和民主決策工具。 分享一款微信投票源碼系統至尊版&#xff0c;集吸粉變現功能二合一&#xff0c;全網獨家支持禮物…

已經安裝tensorflow,仍報錯No module named ‘tensorflow‘

在安裝某些python虛擬環境的教程文章中&#xff0c;經常看到有評論區說安裝了但是調用顯示無模塊&#xff0c;例如pytorch和tensorflow等等。 其實跟之前我寫過的一篇文章解決方法類似&#xff0c;就是python項目中需要應用哪個虛擬環境&#xff0c;這個項目的python解釋器就選…

企業網絡需求及適合的解決方案

近年來&#xff0c;企業網絡通信需求可謂五花八門&#xff0c;變幻莫測。它不僅為企業的生產、辦公、研發、銷售提供全面賦能&#xff0c;同時也讓企業業務規模變大成為了可能。 在當前的技術格局下&#xff0c;中大型企業常見的技術方案有很多&#xff0c;而同時也有各自不可替…

商務英語口語成人考級外語培訓之BECkao考級口語篇

在口語考試中&#xff0c;不管實際內容你能說出多少&#xff0c;但準備一些套話&#xff0c;至少還能撐撐場子你們說是不是&#xff1f; 內容闡述 描述事實 1.Im going to describe/present/explain/give you some information about... 2.Id like to say a few words about...…

德國儲能項目鋰電池儲能集裝箱突發火災:安全挑戰再引關注

2024年4月27日&#xff0c;德國尼爾莫爾商業區的一起鋰電池儲能集裝箱火災事件引起了全球關注。這起事故不僅導致兩名消防員在救援過程中受傷&#xff0c;更暴露了儲能系統在安全領域亟待解決的重要問題。 根據德國消防隊的出警記錄&#xff0c;火災發生在晚上9點前不久。消防人…

機器學習算法應用——神經網絡回歸任務、神經網絡分類任務

神經網絡回歸任務&#xff08;4-3&#xff09; 神經網絡回歸任務&#xff0c;通常指的是使用神經網絡模型進行回歸分析。回歸分析是一種統計學方法&#xff0c;用于研究一個或多個自變量&#xff08;預測變量&#xff09;與一個因變量&#xff08;響應變量&#xff09;之間的關…

漲薪技術 —— 搞定Appium工作中常見應用操作!

前言 Appium 是一個開源、跨平臺的自動化測試工具&#xff0c;用于測試原生和輕量移動應用&#xff0c;支持 iOS, Android 和 FirefoxOS 平臺。此工具在測試工作中也較長用到&#xff0c;接下來給大家介紹日常中的操作。 1、應用操作 1.1獲取應用的包名和界面名 當我們從一…

日報表定時任務優化歷程

報表需求背景 報表是一個很常見的需求&#xff0c;在項目中后期往往會需要加多種維度的一些統計信息&#xff0c;今天就來談談上線近10個月后的一次報表優化優化之路&#xff08;從一天報表跑需要五分鐘&#xff0c;優化至秒級&#xff09; 需求&#xff1a;對代理商進行日統計…

基礎I/O:文件系統調用接口

文章目錄 文件系統調用接口open系統調用接口和C語言封裝文件描述符fd重定向 文件系統調用接口 open NAME//打開、創建 - 打開并可能創建文件或設備open, creat - open and possibly create a file or deviceSYNOPSIS#include <sys/types.h>#include <sys/stat.h>…

【C++算法】隊列相關經典算法題

1. N叉樹的層序遍歷 首先我們遇到這個題目&#xff0c;沒有任何思路&#xff0c;我們就可以來模擬一下層序的流程&#xff0c;首先我們肯定是訪問根節點1&#xff0c;訪問之后呢就是訪問下一層的最左節點3&#xff0c;此時第一層的節點1已經訪問過了就可以不要了&#xff0c;然…

[GESP樣題 四級] 填幻方和幸運數

B3940 [GESP樣題 四級] 填幻方 題目 在一個NN 的正方形網格中&#xff0c;每個格子分別填上從 1 到 NN 的正整數&#xff0c;使得正方形中任一行、任一列及對角線的幾個數之和都相等&#xff0c;則這種正方形圖案就稱為“幻方”&#xff08;輸出樣例中展示了一個33 的幻方&am…

ICode國際青少年編程競賽- Python-4級訓練場-嵌套for循環練習

ICode國際青少年編程競賽- Python-4級訓練場-嵌套for循環練習 1、 for i in range(3):Spaceship.step(4)for j in range(4):Dev.step(2)Dev.turnRight()Spaceship.turnLeft()Spaceship.step(4)Spaceship.turnRight()2、 for i in range(4):Spaceship.step(6)for j in range(3):…

Nginx或Tengine服務器配置SSL證書

目錄 前提條件 步驟一&#xff1a;下載SSL證書 步驟二&#xff1a;在Nginx服務器安裝證書 步驟三&#xff1a;驗證SSL證書是否配置成功 前提條件 已通過數字證書管理服務控制臺簽發證書SSL證書綁定的域名已完成DNS解析&#xff0c;即您的域名與主機IP地址相互映射已在Web服…

維修Philips IU22飛利浦四維多普勒彩超診斷儀 V6-2 L12-5 C8-4V深圳捷達工控維修

專為新時代而設計。專為更多而設計。 超聲波在抗擊 COVID-19 中的成像作用不斷擴大&#xff0c;并且對血管和心臟檢查的需求不斷增加&#xff0c;因此比以往任何時候都更有價值。飛利浦的超聲產品組合&#xff08;包括 EPIQ Elite&#xff09;為一線護理人員提供了寶貴的診斷支…

Intel處理器7z/XZ遇到 The failure in hardware

最近在使用Intel 12700H混合架構處理器的時候&#xff0c;一旦使用7z或者XZ算法壓縮東西就會出現如下的報錯&#xff1a; Internal Error: The failure in hardware (RAM or CPU), OS or program在檢查排除了內存、磁盤和OS的問題后&#xff0c;最終確定為Intel CPU的問題&…

Lazada、Shopee測評自養號,快速出單技巧全解析!

每個人都憧憬著自己的店鋪能夠擁有一款或多款引人注目的熱銷商品&#xff0c;這些商品不僅能為店鋪帶來可觀的收益&#xff0c;更重要的是它們能夠成為吸引顧客的強大磁石&#xff0c;顯著提升店鋪的整體流量。一旦這樣的爆款商品成功吸引顧客&#xff0c;其他產品也將隨之受到…