生活随笔
收集整理的這篇文章主要介紹了
视频过滤器案例
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
視頻過濾器案例
目錄
AVFilter主體框架流程視頻過濾器案例代碼實現(xiàn)graph顯示
1. AVFilter主體框架流程
在利?AVFilter進??視頻數(shù)據(jù)處理前先將在進?的處理流程繪制出來,現(xiàn)在以FFmpeg filter官??檔中的?個例?為例進?說明。
這個例?的處理流程如上所示,?先使?split濾波器將input流分成兩路流(main和tmp),然后分別對兩路流進?處理。對于tmp流,先經(jīng)過crop濾波器進?裁剪處理,再經(jīng)過flip濾波器進?垂直?向上的翻轉操作,輸出的結果命名為flip流。再將main流和flip流輸?到overlay濾波器進?合成操作。上圖的input就是上?提過的buffer源濾波器,output就是上?的提過的buffersink濾波器。上圖中每個節(jié)點都是?個AVFilterContext,每個連線就是AVFliterLink。所有這些信息都統(tǒng)?由AVFilterGraph來管理。
2. 視頻過濾器案例代碼實現(xiàn)
#include
<stdio
.h
>#include
<libavcodec
/avcodec
.h
>
#include
<libavformat
/avformat
.h
>
#include
<libavfilter
/avfilter
.h
>
#include
<libavfilter
/buffersink
.h
>
#include
<libavfilter
/buffersrc
.h
>
#include
<libavutil
/opt
.h
>
#include
<libavutil
/imgutils
.h
>int main(int argc
, char
*argv
) {int ret
= 0;FILE
*inFile
= NULL
;const char
*inFileName
= "768x320.yuv";fopen_s(&inFile
, inFileName
, "rb+");if (!inFile
) {printf("Fail to open file\n");return -1;}int in_width
= 768;int in_height
= 320;FILE
*outFile
= NULL
;const char
*outFileName
= "out_crop_vfilter.yuv";fopen_s(&outFile
, outFileName
, "wb");if (!outFile
) {printf("Fail to create file for output\n");return -1;}avfilter_register_all();AVFilterGraph
*filter_graph
= avfilter_graph_alloc();if (!filter_graph
) {printf("Fail to create filter graph!\n");return -1;}char args
[512];sprintf(args
,"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",in_width
, in_height
, AV_PIX_FMT_YUV420P
,1, 25, 1, 1);AVFilter
*bufferSrc
= avfilter_get_by_name("buffer"); AVFilterContext
*bufferSrc_ctx
;ret
= avfilter_graph_create_filter(&bufferSrc_ctx
, bufferSrc
, "in", args
, NULL
, filter_graph
);if (ret
< 0) {printf("Fail to create filter bufferSrc\n");return -1;}AVBufferSinkParams
*bufferSink_params
;AVFilterContext
*bufferSink_ctx
;AVFilter
*bufferSink
= avfilter_get_by_name("buffersink");enum AVPixelFormat pix_fmts
[] = {AV_PIX_FMT_YUV420P
, AV_PIX_FMT_NONE
};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("Fail to create filter sink filter\n");return -1;}AVFilter
*splitFilter
= avfilter_get_by_name("split");AVFilterContext
*splitFilter_ctx
;ret
= avfilter_graph_create_filter(&splitFilter_ctx
, splitFilter
, "split", "outputs=2",NULL
, filter_graph
);if (ret
< 0) {printf("Fail to create split filter\n");return -1;}AVFilter
*cropFilter
= avfilter_get_by_name("crop");AVFilterContext
*cropFilter_ctx
;ret
= avfilter_graph_create_filter(&cropFilter_ctx
, cropFilter
, "crop","out_w=iw:out_h=ih/2:x=0:y=0", NULL
, filter_graph
);if (ret
< 0) {printf("Fail to create crop filter\n");return -1;}AVFilter
*vflipFilter
= avfilter_get_by_name("vflip");AVFilterContext
*vflipFilter_ctx
;ret
= avfilter_graph_create_filter(&vflipFilter_ctx
, vflipFilter
, "vflip", NULL
, NULL
, filter_graph
);if (ret
< 0) {printf("Fail to create vflip filter\n");return -1;}AVFilter
*overlayFilter
= avfilter_get_by_name("overlay");AVFilterContext
*overlayFilter_ctx
;ret
= avfilter_graph_create_filter(&overlayFilter_ctx
, overlayFilter
, "overlay","y=0:H/2", NULL
, filter_graph
);if (ret
< 0) {printf("Fail to create overlay filter\n");return -1;}ret
= avfilter_link(bufferSrc_ctx
, 0, splitFilter_ctx
, 0);if (ret
!= 0) {printf("Fail to link src filter and split filter\n");return -1;}ret
= avfilter_link(splitFilter_ctx
, 0, overlayFilter_ctx
, 0);if (ret
!= 0) {printf("Fail to link split filter and overlay filter main pad\n");return -1;}ret
= avfilter_link(splitFilter_ctx
, 1, cropFilter_ctx
, 0);if (ret
!= 0) {printf("Fail to link split filter's second pad and crop filter\n");return -1;}ret
= avfilter_link(cropFilter_ctx
, 0, vflipFilter_ctx
, 0);if (ret
!= 0) {printf("Fail to link crop filter and vflip filter\n");return -1;}ret
= avfilter_link(vflipFilter_ctx
, 0, overlayFilter_ctx
, 1);if (ret
!= 0) {printf("Fail to link vflip filter and overlay filter's second pad\n");return -1;}ret
= avfilter_link(overlayFilter_ctx
, 0, bufferSink_ctx
, 0);if (ret
!= 0) {printf("Fail to link overlay filter and sink filter\n");return -1;}ret
= avfilter_graph_config(filter_graph
, NULL
);if (ret
< 0) {printf("Fail in filter graph\n");return -1;}char
*graph_str
= avfilter_graph_dump(filter_graph
, NULL
);FILE
*graphFile
= NULL
;fopen_s(&graphFile
, "graphFile.txt", "w"); fprintf(graphFile
, "%s", graph_str
);av_free(graph_str
);AVFrame
*frame_in
= av_frame_alloc();unsigned char
*frame_buffer_in
= (unsigned char
*) av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P
, in_width
, in_height
, 1));av_image_fill_arrays(frame_in
->data
, frame_in
->linesize
, frame_buffer_in
,AV_PIX_FMT_YUV420P
, in_width
, in_height
, 1);AVFrame
*frame_out
= av_frame_alloc();unsigned char
*frame_buffer_out
= (unsigned char
*) av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P
, in_width
, in_height
, 1));av_image_fill_arrays(frame_out
->data
, frame_out
->linesize
, frame_buffer_out
,AV_PIX_FMT_YUV420P
, in_width
, in_height
, 1);frame_in
->width
= in_width
;frame_in
->height
= in_height
;frame_in
->format
= AV_PIX_FMT_YUV420P
;uint32_t frame_count
= 0;while
(1) {if (fread(frame_buffer_in
, 1, in_width
* in_height
* 3 / 2, inFile
) != in_width
* in_height
* 3 / 2) {break;}frame_in
->data
[0] = frame_buffer_in
;frame_in
->data
[1] = frame_buffer_in
+ in_width
* in_height
;frame_in
->data
[2] = frame_buffer_in
+ in_width
* in_height
* 5 / 4;if (av_buffersrc_add_frame(bufferSrc_ctx
, frame_in
) < 0) {printf("Error while add frame.\n");break;}ret
= av_buffersink_get_frame(bufferSink_ctx
, frame_out
);if (ret
< 0)break;if (frame_out
->format
== AV_PIX_FMT_YUV420P
) {for (int i
= 0; i
< frame_out
->height
; i
++) {fwrite(frame_out
->data
[0] + frame_out
->linesize
[0] * i
, 1, frame_out
->width
, outFile
);}for (int i
= 0; i
< frame_out
->height
/ 2; i
++) {fwrite(frame_out
->data
[1] + frame_out
->linesize
[1] * i
, 1, frame_out
->width
/ 2, outFile
);}for (int i
= 0; i
< frame_out
->height
/ 2; i
++) {fwrite(frame_out
->data
[2] + frame_out
->linesize
[2] * i
, 1, frame_out
->width
/ 2, outFile
);}}++frame_count
;if (frame_count
% 25 == 0)printf("Process %d frame!\n", frame_count
);av_frame_unref(frame_out
);}fclose(inFile
);fclose(outFile
);av_frame_free(&frame_in
);av_frame_free(&frame_out
);avfilter_graph_free(&filter_graph
); return 0;
}
3. graph顯示
+----------+
| in
|default--[768x320
1:1 yuv420p
]--split
:default
| (buffer
) |
+----------++--------------+
overlay
:default--[768x320
1:1 yuv420p
]--default| out
|| (buffersink
) |+--------------++---------+
in
:default--[768x320
1:1 yuv420p
]--default| split
|output0
--[768x320
1:1 yuv420p
]--overlay
:main
| (split
) |output1
--[768x320
1:1 yuv420p
]--crop
:default+---------++--------+
split
:output1
--[768x320
1:1 yuv420p
]--default| crop
|default--[768x160
1:1 yuv420p
]--vflip
:default| (crop
) |+--------++---------+
crop
:default--[768x160
1:1 yuv420p
]--default| vflip
|default--[768x160
1:1 yuv420p
]--auto_scaler_0
:default| (vflip
) |+---------++-----------+
split
:output0
----------[768x320
1:1 yuv420p
]------main
| overlay
|default--[768x320
1:1 yuv420p
]--out
:default
auto_scaler_0
:default--[768x160
1:1 yuva420p
]--overlay
| (overlay
) |+-----------++---------------+
vflip
:default--[768x160
1:1 yuv420p
]--default| auto_scaler_0
|default--[768x160
1:1 yuva420p
]--overlay
:overlay
| (scale
) |+---------------+
總結
以上是生活随笔為你收集整理的视频过滤器案例的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。