生活随笔
收集整理的這篇文章主要介紹了
使用ffmpeg 的 filter 给图片添加水印
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
使用ffmpeg 的 filter 給圖片添加水印。
main.c
#include <stdio.h>#include <libavfilter/avfilter.h>
#include <libavfilter/buffersrc.h>
#include <libavfilter/buffersink.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>AVFilterContext
* mainsrc_ctx
= NULL;
AVFilterContext
* logosrc_ctx
= NULL;
AVFilterContext
* resultsink_ctx
= NULL;
AVFilterGraph
* filter_graph
= NULL;
static int init_filters(const AVFrame
* main_frame
, const AVFrame
* logo_frame
, int x
, int y
)
{int ret
= 0;AVFilterInOut
* inputs
= NULL;AVFilterInOut
* outputs
= NULL;char filter_args
[1024] = {0};filter_graph
= avfilter_graph_alloc();if(!filter_graph
){printf("%d : avfilter_graph_alloc() failed!\n", __LINE__);return -1;}snprintf(filter_args
, sizeof(filter_args
),"buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/25:pixel_aspect=%d/%d[main];" "buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/25:pixel_aspect=%d/%d[logo];" "[main][logo]overlay=%d:%d[result];" "[result]buffersink", main_frame
->width
, main_frame
->height
, main_frame
->format
, main_frame
->sample_aspect_ratio
.num
, main_frame
->sample_aspect_ratio
.den
,logo_frame
->width
, logo_frame
->height
, logo_frame
->format
, logo_frame
->sample_aspect_ratio
.num
, logo_frame
->sample_aspect_ratio
.den
,x
, y
);ret
= avfilter_graph_parse2(filter_graph
, filter_args
, &inputs
, &outputs
);if(ret
< 0){printf("%d : avfilter_graph_parse2() failed!\n", __LINE__);return ret
;}ret
= avfilter_graph_config(filter_graph
, NULL);if(ret
< 0){printf("%d : avfilter_graph_config() failed!\n", __LINE__);return ret
;}mainsrc_ctx
= avfilter_graph_get_filter(filter_graph
, "Parsed_buffer_0");logosrc_ctx
= avfilter_graph_get_filter(filter_graph
, "Parsed_buffer_1");resultsink_ctx
= avfilter_graph_get_filter(filter_graph
, "Parsed_buffersink_3");avfilter_inout_free(&inputs
);avfilter_inout_free(&outputs
);return 0;
}
static int main_mix_logo(AVFrame
* main_frame
, AVFrame
* logo_frame
, AVFrame
*result_frame
)
{int ret
= 0;ret
= av_buffersrc_add_frame(mainsrc_ctx
, main_frame
);if(ret
< 0)return ret
;ret
= av_buffersrc_add_frame(logosrc_ctx
, logo_frame
);if(ret
< 0)return ret
;ret
= av_buffersink_get_frame(resultsink_ctx
, result_frame
);return ret
;}static AVFrame
* get_jpeg(const char* filename
)
{int ret
= 0;AVFormatContext
* format_ctx
= NULL;if((ret
= avformat_open_input(&format_ctx
, filename
, NULL, NULL)) != 0){printf("%d : avformat_open_input() failed!\n");return NULL;}avformat_find_stream_info(format_ctx
, NULL);AVCodec
* codec
= NULL;AVCodecContext
* codec_ctx
= NULL;int video_stream_index
= -1;video_stream_index
= av_find_best_stream(format_ctx
, AVMEDIA_TYPE_VIDEO
, -1, -1, &codec
, 0);if(video_stream_index
< 0)goto cleanup
;codec_ctx
= avcodec_alloc_context3(codec
);ret
= avcodec_open2(codec_ctx
, codec
, NULL);if(ret
< 0)goto cleanup
;AVPacket pkt
;av_init_packet(&pkt
);pkt
.data
= NULL;pkt
.size
= 0;ret
= av_read_frame(format_ctx
, &pkt
);if(ret
< 0)goto cleanup
;ret
= avcodec_send_packet(codec_ctx
, &pkt
);if(ret
< 0)goto cleanup
;AVFrame
* frame
= av_frame_alloc();ret
= avcodec_receive_frame(codec_ctx
, frame
);if(ret
< 0)av_frame_free(&frame
);cleanup
:if(format_ctx
)avformat_close_input(&format_ctx
);if(codec_ctx
)avcodec_free_context(&codec_ctx
);return frame
;
}static int savejpeg(const char* filename
, const AVFrame
* frame
)
{AVCodec
* jpeg_codec
= avcodec_find_encoder(AV_CODEC_ID_MJPEG
);if(!jpeg_codec
)return -1;AVCodecContext
* jpeg_codec_ctx
= avcodec_alloc_context3(jpeg_codec
);if(!jpeg_codec_ctx
)return -2;jpeg_codec_ctx
->pix_fmt
= AV_PIX_FMT_YUVJ420P
;jpeg_codec_ctx
->width
= frame
->width
;jpeg_codec_ctx
->height
= frame
->height
;jpeg_codec_ctx
->time_base
.num
= 1;jpeg_codec_ctx
->time_base
.den
= 25;jpeg_codec_ctx
->framerate
.num
= 25;jpeg_codec_ctx
->framerate
.den
= 1;AVDictionary
* encoder_opts
= NULL;av_dict_set(&encoder_opts
, "flags", "+qscale", 0);av_dict_set(&encoder_opts
, "qmax", "2", 0);av_dict_set(&encoder_opts
, "qmin", "2", 0);int ret
= avcodec_open2(jpeg_codec_ctx
, jpeg_codec
, &encoder_opts
);if(ret
< 0){avcodec_free_context(&jpeg_codec_ctx
);printf("%d : avcodec_open2() failed!\n");return -3;}av_dict_free(&encoder_opts
);AVPacket pkt
;av_init_packet(&pkt
);pkt
.data
= NULL;pkt
.size
= 0;ret
= avcodec_send_frame(jpeg_codec_ctx
, frame
);if(ret
< 0){avcodec_free_context(&jpeg_codec_ctx
);printf("%d : avcodec_send_frame() failed!\n");return -4;}ret
= 0;while(ret
>= 0){ret
= avcodec_receive_packet(jpeg_codec_ctx
, &pkt
);if(ret
== AVERROR(EAGAIN
))continue;if(ret
== AVERROR_EOF
){ret
= 0;break;}FILE
* outfile
= fopen(filename
, "wb");if(!outfile
){printf("%d : fopen() failed!\n");ret
= -1;break;}if(fwrite((char*)pkt
.data
, 1, pkt
.size
, outfile
) == pkt
.size
){ret
= 0;}else{printf("%d : fwrite failed!\n");ret
= -1;}fclose(outfile
);ret
= 0;break;}avcodec_free_context(&jpeg_codec_ctx
);return ret
;
}int main()
{printf("Hello watermarkmix!\n");AVFrame
*main_frame
= get_jpeg("main.jpg");AVFrame
*logo_frame
= get_jpeg("logo.jpg");AVFrame
* result_frame
= av_frame_alloc();int ret
= 0;if(ret
= init_filters(main_frame
, logo_frame
, 100, 200) < 0) {printf("%d : init_filters failed\n", __LINE__);goto end
;}if(main_mix_logo(main_frame
, logo_frame
, result_frame
) < 0) {printf("%d : main_picture_mix_logo failed\n", __LINE__);goto end
;}savejpeg("output.jpg", result_frame
);
end
:if(main_frame
)av_frame_free(&main_frame
);if(logo_frame
)av_frame_free(&logo_frame
);if(result_frame
)av_frame_free(&result_frame
);if(filter_graph
)avfilter_graph_free(&filter_graph
);printf("finish\n");printf("End watermarkmix!\n");return 0;
}
總結(jié)
以上是生活随笔為你收集整理的使用ffmpeg 的 filter 给图片添加水印的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。