FFMPEG中的libswscale是做像素转换的,但是对于一些复杂的操作,比如添加水印等,这个库就不行了,这时候就要说一下另外一个AVFilter。AVFilter完全可以替代libswscale的所有功能,也许有一天,ffmpeg也会这样去做。AVFilter虽然学起来有点复杂,但是为了学好FFMPEG,为了涨工资,我忍了。(*^__^*) 嘻嘻……

概念:

做个directshow的同学,对于这一块应该很了解了。

1.AVFilterGraph:和dshow中的filtergraph功能基本上一样,管理filter的,可以看成filter的一个容器。

2.AVFilter:就是一个filter啦。但是为什么叫做filter,其实就是一个过滤器,目标资源通过该过滤器总该发生一点变化是吧。。。。。

3.AVFilterLink:代表两个filter的关联媒介。

4.AVFilterPad:代表一个filter的输入输出口,就跟dshow中的pin差不多。只有输入pad的叫做source,只有输出pad的叫做sink。

下面是官方提供的一个例子:

  1. /*
  2. *modifier by tongli
  3. */
  4. #define _XOPEN_SOURCE 600
  5. #include <stdio.h>
  6. #include <windows.h>
  7. #include "snprintf.h"
  8. extern "C"
  9. {
  10. #include <libavcodec/avcodec.h>
  11. #include <libavformat/avformat.h>
  12. #include <libavfilter/avfiltergraph.h>
  13. #include <libavfilter/avcodec.h>
  14. #include <libavfilter/buffersink.h>
  15. #include <libavfilter/buffersrc.h>
  16. #include <libavutil/opt.h>
  17. }
  18. const char *filter_descr = "scale=78:24";
  19. static AVFormatContext *fmt_ctx;
  20. static AVCodecContext *dec_ctx;
  21. AVFilterContext *buffersink_ctx;
  22. AVFilterContext *buffersrc_ctx;
  23. AVFilterGraph *filter_graph;
  24. static int video_stream_index = -1;
  25. static int64_t last_pts = AV_NOPTS_VALUE;
  26. static int open_input_file(const char *filename)
  27. {
  28. int ret;
  29. AVCodec *dec;
  30. if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {
  31. av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
  32. return ret;
  33. }
  34. if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
  35. av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
  36. return ret;
  37. }
  38. /* select the video stream */
  39. ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);
  40. if (ret < 0) {
  41. av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n");
  42. return ret;
  43. }
  44. video_stream_index = ret;
  45. dec_ctx = fmt_ctx->streams[video_stream_index]->codec;
  46. av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);
  47. /* init the video decoder */
  48. if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
  49. av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n");
  50. return ret;
  51. }
  52. return 0;
  53. }
  54. static int init_filters(const char *filters_descr)
  55. {
  56. char args[512];
  57. int ret = 0;
  58. AVFilter *buffersrc = avfilter_get_by_name("buffer");
  59. AVFilter *buffersink = avfilter_get_by_name("buffersink");
  60. AVFilterInOut *outputs = avfilter_inout_alloc();
  61. AVFilterInOut *inputs = avfilter_inout_alloc();
  62. AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base;
  63. enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
  64. filter_graph = avfilter_graph_alloc();
  65. if (!outputs || !inputs || !filter_graph) {
  66. ret = AVERROR(ENOMEM);
  67. goto end;
  68. }
  69. /* buffer video source: the decoded frames from the decoder will be inserted here. */
  70. snprintf(args, sizeof(args),
  71. "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
  72. dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
  73. time_base.num, time_base.den,
  74. dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den);
  75. ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  76. args, NULL, filter_graph);
  77. if (ret < 0) {
  78. av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
  79. goto end;
  80. }
  81. /* buffer video sink: to terminate the filter chain. */
  82. ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  83. NULL, NULL, filter_graph);
  84. if (ret < 0) {
  85. av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
  86. goto end;
  87. }
  88. ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
  89. AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
  90. if (ret < 0) {
  91. av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
  92. goto end;
  93. }
  94. /* Endpoints for the filter graph. */
  95. outputs->name = av_strdup("in");
  96. outputs->filter_ctx = buffersrc_ctx;
  97. outputs->pad_idx = 0;
  98. outputs->next = NULL;
  99. inputs->name = av_strdup("out");
  100. inputs->filter_ctx = buffersink_ctx;
  101. inputs->pad_idx = 0;
  102. inputs->next = NULL;
  103. if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr,
  104. &inputs, &outputs, NULL)) < 0)
  105. goto end;
  106. if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
  107. goto end;
  108. end:
  109. avfilter_inout_free(&inputs);
  110. avfilter_inout_free(&outputs);
  111. return ret;
  112. }
  113. static void display_frame(const AVFrame *frame, AVRational time_base)
  114. {
  115. int x, y;
  116. uint8_t *p0, *p;
  117. int64_t delay;
  118. AVRational ar_base_q = { 1, AV_TIME_BASE };
  119. if (frame->pts != AV_NOPTS_VALUE) {
  120. if (last_pts != AV_NOPTS_VALUE) {
  121. /* sleep roughly the right amount of time;
  122. * usleep is in microseconds, just like AV_TIME_BASE. */
  123. delay = av_rescale_q(frame->pts - last_pts,
  124. time_base, ar_base_q);
  125. if (delay > 0 && delay < 1000000)
  126. //usleep(delay);
  127. Sleep(delay);
  128. }
  129. last_pts = frame->pts;
  130. }
  131. /* Trivial ASCII grayscale display. */
  132. p0 = frame->data[0];
  133. puts("\033c");
  134. for (y = 0; y < frame->height; y++) {
  135. p = p0;
  136. for (x = 0; x < frame->width; x++)
  137. putchar(" .-+#"[*(p++) / 52]);
  138. putchar('\n');
  139. p0 += frame->linesize[0];
  140. }
  141. fflush(stdout);
  142. }
  143. int main(int argc, char **argv)
  144. {
  145. int ret;
  146. AVPacket packet;
  147. AVFrame *frame = av_frame_alloc();
  148. AVFrame *filt_frame = av_frame_alloc();
  149. int got_frame;
  150. if (!frame || !filt_frame) {
  151. perror("Could not allocate frame");
  152. exit(1);
  153. }
  154. av_register_all();
  155. avfilter_register_all();
  156. if ((ret = open_input_file("style.ts")) < 0)
  157. goto end;
  158. if ((ret = init_filters(filter_descr)) < 0)
  159. goto end;
  160. /* read all packets */
  161. while (1) {
  162. if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)
  163. break;
  164. if (packet.stream_index == video_stream_index) {
  165. got_frame = 0;
  166. ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet);
  167. if (ret < 0) {
  168. av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");
  169. break;
  170. }
  171. if (got_frame) {
  172. frame->pts = av_frame_get_best_effort_timestamp(frame);
  173. /* push the decoded frame into the filtergraph */
  174. if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
  175. av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
  176. break;
  177. }
  178. /* pull filtered frames from the filtergraph */
  179. while (1) {
  180. ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
  181. if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  182. break;
  183. if (ret < 0)
  184. goto end;
  185. display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
  186. av_frame_unref(filt_frame);
  187. }
  188. av_frame_unref(frame);
  189. }
  190. }
  191. av_free_packet(&packet);
  192. }
  193. end:
  194. avfilter_graph_free(&filter_graph);
  195. avcodec_close(dec_ctx);
  196. avformat_close_input(&fmt_ctx);
  197. av_frame_free(&frame);
  198. av_frame_free(&filt_frame);
  199. if (ret < 0 && ret != AVERROR_EOF) {
  200. fprintf(stderr, "Error occurred: %s\n"); //av_err2str(ret));
  201. exit(1);
  202. }
  203. exit(0);
  204. }

未完待续。。。。

FFMPEG-AVFilter研究的更多相关文章

  1. 最简单的基于FFmpeg的AVfilter例子(水印叠加)

    ===================================================== 最简单的基于FFmpeg的AVfilter例子系列文章: 最简单的基于FFmpeg的AVfi ...

  2. 最简单的基于FFmpeg的AVfilter样例(水印叠加)

    ===================================================== 最简单的基于FFmpeg的AVfilter样例系列文章: 最简单的基于FFmpeg的AVfi ...

  3. 最简单的基于FFMPEG的图像编码器(YUV编码为JPEG)

    伴随着毕业论文的完成,这两天终于腾出了空闲,又有时间搞搞FFMPEG的研究了.想着之前一直搞的都是FFMPEG解码方面的工作,很少涉及到FFMPEG编码方面的东西,于是打算研究一下FFMPEG的编码. ...

  4. (一) ffmpeg filter学习-使用流程

    FFMPEG中有一个类库:libavfilter.该类库提供了各种视音频过滤器.之前一直没有怎么使用过这个类库,最近看了一下它的使用说明,发现还是很强大的,有很多现成的filter供使用,完成视频的处 ...

  5. 最简单的基于FFMPEG的图像编码器(YUV编码为JPEG)(转)

    原文转自 https://blog.csdn.net/leixiaohua1020/article/details/25346147/ 伴随着毕业论文的完成,这两天终于腾出了空闲,又有时间搞搞FFMP ...

  6. FFmpeg源代码结构图

    转自:http://blog.csdn.net/leixiaohua1020/article/details/44220151 FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码 ...

  7. FFmpeg源码结构图 - 解码

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  8. FFmpeg源代码结构图 - 解码

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. Android 音视频深入 十 FFmpeg给视频加特效(附源码下载)

    项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(AVfilte ...

  10. ffmpeg命令汇总

    1. 查看ffmpeg信息: ldd `which ffmpeg` ffmpeg -filters ffmpeg -h filter=drawtext man ffmpeg ffmpeg --help ...

随机推荐

  1. mxnet编译问题手记

    MXNet在64位Win7下的编译安装:https://www.cnblogs.com/noahzn/p/5506086.html http://blog.csdn.net/Jarvis_wxy/ar ...

  2. urllib.urlencode() 无法encode中文, UnicodeEncodeError

    urllib.urlencode() 无法encode中文, UnicodeEncodeError, 具体错误内容如下:File "/System/Library/Frameworks/Py ...

  3. Razor里写函数

    asp.net mvc的视图里使用Razor来书写服务器代码,人尽皆知.可以常常见到里面写上for循环语句,输出一大堆东东,牛逼得很. 可是,如果循环语句还不能满足我们的要求,需要定义一个函数来调用, ...

  4. Office Web Apps 2013对文档的精细定位

    在一般情况下,我们使用Office Web Apps查看文档都是从第一页开始查看,不过在SharePoint搜索中,我们看到这样的结果: 这是2013搜索的一个新特性,可以深入定位到文档内部,支持PP ...

  5. 九度OJ 1002:Grading

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:18410 解决:4753 题目描述: Grading hundreds of thousands of Graduate Entrance ...

  6. Convex combination

    en.wikipedia.org/wiki/Convex_combination 凸组合 In convex geometry, a convex combination is a linear co ...

  7. python学习-1-列表,元组,字典,集合,文件操作

    1. 列表.元组操作 names = ['Alex',"Tenglan",'Eric'] >>> names[0] >>> names[2] & ...

  8. Vue:实践学习笔记(1)——快速使用

    Vue:实践学习笔记(1)——快速使用 Vue基础知识 0.引入Vue 官方地址:Vue的官方下载地址 Vue推荐博客:keepfool 在你的程序中快速引入Vue: <!-- 开发环境版本,包 ...

  9. LeetCode:用HashMap解决问题

    LeetCode:用HashMap解决问题 Find Anagram Mappings class Solution { public int[] anagramMappings(int[] A, i ...

  10. java程序实现Unicode码和中文互相转换

      根据前一篇的补充问题http://blog.csdn.net/fancylovejava/article/details/10142391 有了前一篇文章的了解,大概了解了unicode编码格式了 ...