ffmpeg 最简单的水印功能
2017-06-20 15:57
555 查看
ffmpeg中的filter功能不得不说真不错,类似于gstreamer,所有的filter(过滤器)都是相互连接对应的pad来完成数据流在其中的转换的,从src filter进,从sink filter出。相信玩过gstreamer的朋友一定能理解这种模式,如果不明白的朋友可以去gst官网了解下其方式,我本人认为这个比直接看filter来理解更容易。
好了,那水印的添加也是通过avfilter这个模块来做的,主要是通过movie和overlay这两个filter来处理,废话不多说,上代码,主要提供一个最简单的使用avfilter的教程。
代码下载地址:http://download.csdn.net/detail/jiuniangyuanzikk/8037231
点击(此处)折叠或打开
const char* filename = "E:\\C++Learning\\FFMPEG_SDL_WIN32_PLAYER_by_nick_avfilter\\FLV_STREAM\\4.flv";
const char* filters_descr = "[in]scale=1280:720[scale];movie=1.jpg[wm];[scale][wm]overlay=0:0[out]";
int main()
{
FILE *fp_yuv=fopen("test.yuv","wb+");
if(!fp_yuv)
return 0;
int ret = 0;
av_register_all();
avfilter_register_all();
AVFormatContext *pFormat = NULL;
avformat_open_input(&pFormat,filename,NULL,NULL);
if(!pFormat)
return 0;
if (avformat_find_stream_info(pFormat, NULL) < 0)
{
printf("Could not find stream information\n");
}
av_dump_format(pFormat, 0, filename, 0);
AVCodecContext *video_dec_ctx = pFormat->streams[0]->codec;
AVStream *video_st = pFormat->streams[0];
AVCodec *video_dec = avcodec_find_decoder(video_dec_ctx->codec_id);
avcodec_open2(video_dec_ctx, video_dec,NULL);
if(!video_dec_ctx || !video_dec || !video_st)
return 0;
uint8_t *video_dst_data[4] = {NULL};
int video_dst_linesize[4];
int video_dst_bufsize;
ret = av_image_alloc(video_dst_data, video_dst_linesize,
1280, 720,
video_dec_ctx->pix_fmt, 1);
video_dst_bufsize = ret;
AVPacket *pkt=(AVPacket *)malloc(sizeof(AVPacket));
av_init_packet(pkt);
//filter
AVFilter *buffersrc = avfilter_get_by_name("buffer");
AVFilter *buffersink = avfilter_get_by_name("buffersink");
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph;
filter_graph = avfilter_graph_alloc();
if (!outputs || !inputs || !filter_graph) {
ret = AVERROR(ENOMEM);
return 0;
}
char args[512] = {0};
_snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
video_dec_ctx->width, video_dec_ctx->height, video_dec_ctx->pix_fmt,
video_dec_ctx->time_base.num, video_dec_ctx->time_base.den,
video_dec_ctx->sample_aspect_ratio.num, video_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");
return 0;
}
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");
return 0;
}
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 0;
}
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, filters_descr,
&inputs, &outputs, NULL)) < 0)
return 0;
if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
return 0;
int gotpicture = 0;
while(1)
{
av_read_frame(pFormat,pkt);
if(pkt->stream_index == 0)
{
AVFrame* pFrame = avcodec_alloc_frame();
ret = avcodec_decode_video2(video_dec_ctx,pFrame,&gotpicture,pkt);
if(ret<0)
return 0;
if(gotpicture)
{
if (av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, 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) {
AVFrame* filt_frame = avcodec_alloc_frame();
ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF || ret == AVERROR(EIO))
break;
if (ret < 0)
return 0;
//int y_size=filt_frame->width*filt_frame->height;
av_image_copy(video_dst_data, video_dst_linesize,
(const uint8_t **)(filt_frame->data), filt_frame->linesize,
PIX_FMT_YUV420P, filt_frame->width, filt_frame->height);
fwrite(video_dst_data[0], 1, video_dst_bufsize, fp_yuv);
avcodec_free_frame(&filt_frame);
}
avcodec_free_frame(&pFrame);
fclose(fp_yuv);
return 0;
}
else
{
}
printf("video\n");
}
av_free_packet(pkt);
}
return 0;
}
好了,那水印的添加也是通过avfilter这个模块来做的,主要是通过movie和overlay这两个filter来处理,废话不多说,上代码,主要提供一个最简单的使用avfilter的教程。
代码下载地址:http://download.csdn.net/detail/jiuniangyuanzikk/8037231
点击(此处)折叠或打开
const char* filename = "E:\\C++Learning\\FFMPEG_SDL_WIN32_PLAYER_by_nick_avfilter\\FLV_STREAM\\4.flv";
const char* filters_descr = "[in]scale=1280:720[scale];movie=1.jpg[wm];[scale][wm]overlay=0:0[out]";
int main()
{
FILE *fp_yuv=fopen("test.yuv","wb+");
if(!fp_yuv)
return 0;
int ret = 0;
av_register_all();
avfilter_register_all();
AVFormatContext *pFormat = NULL;
avformat_open_input(&pFormat,filename,NULL,NULL);
if(!pFormat)
return 0;
if (avformat_find_stream_info(pFormat, NULL) < 0)
{
printf("Could not find stream information\n");
}
av_dump_format(pFormat, 0, filename, 0);
AVCodecContext *video_dec_ctx = pFormat->streams[0]->codec;
AVStream *video_st = pFormat->streams[0];
AVCodec *video_dec = avcodec_find_decoder(video_dec_ctx->codec_id);
avcodec_open2(video_dec_ctx, video_dec,NULL);
if(!video_dec_ctx || !video_dec || !video_st)
return 0;
uint8_t *video_dst_data[4] = {NULL};
int video_dst_linesize[4];
int video_dst_bufsize;
ret = av_image_alloc(video_dst_data, video_dst_linesize,
1280, 720,
video_dec_ctx->pix_fmt, 1);
video_dst_bufsize = ret;
AVPacket *pkt=(AVPacket *)malloc(sizeof(AVPacket));
av_init_packet(pkt);
//filter
AVFilter *buffersrc = avfilter_get_by_name("buffer");
AVFilter *buffersink = avfilter_get_by_name("buffersink");
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph;
filter_graph = avfilter_graph_alloc();
if (!outputs || !inputs || !filter_graph) {
ret = AVERROR(ENOMEM);
return 0;
}
char args[512] = {0};
_snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
video_dec_ctx->width, video_dec_ctx->height, video_dec_ctx->pix_fmt,
video_dec_ctx->time_base.num, video_dec_ctx->time_base.den,
video_dec_ctx->sample_aspect_ratio.num, video_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");
return 0;
}
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");
return 0;
}
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 0;
}
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, filters_descr,
&inputs, &outputs, NULL)) < 0)
return 0;
if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
return 0;
int gotpicture = 0;
while(1)
{
av_read_frame(pFormat,pkt);
if(pkt->stream_index == 0)
{
AVFrame* pFrame = avcodec_alloc_frame();
ret = avcodec_decode_video2(video_dec_ctx,pFrame,&gotpicture,pkt);
if(ret<0)
return 0;
if(gotpicture)
{
if (av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, 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) {
AVFrame* filt_frame = avcodec_alloc_frame();
ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF || ret == AVERROR(EIO))
break;
if (ret < 0)
return 0;
//int y_size=filt_frame->width*filt_frame->height;
av_image_copy(video_dst_data, video_dst_linesize,
(const uint8_t **)(filt_frame->data), filt_frame->linesize,
PIX_FMT_YUV420P, filt_frame->width, filt_frame->height);
fwrite(video_dst_data[0], 1, video_dst_bufsize, fp_yuv);
avcodec_free_frame(&filt_frame);
}
avcodec_free_frame(&pFrame);
fclose(fp_yuv);
return 0;
}
else
{
}
printf("video\n");
}
av_free_packet(pkt);
}
return 0;
}
相关文章推荐
- ffmpeg 最简单的水印功能
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- 使用ffmpeg的concat可以实现简单的流文件合并功能。
- simpleImageTool又一纯java的简单而功能强的专门图片水印、缩放库,给gif加水印也很简单
- ffmpeg实战教程(八)Android平台下AVfilter 实现水印,滤镜等特效功能
- php加水印简单功能
- ASP.NET简单好用功能齐全图片上传工具类(水印、缩略图、裁剪等)
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- ffmpeg学习4--ffmpeg类的简单封装,包含解码和定时录像功能
- simpleImageTool又一纯java的简单而功能强的专门图片水印、缩放库,给gif加水印也很简单
- FFmpeg在Linux下的简单安装并与Java结合获取视频缩略图功能实现
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- ASP.NET简单好用功能齐全图片上传工具类(水印、缩略图、裁剪等)
- javaCV开发详解之技术杂烩:javaCV能帮我们做什么?能实现什么功能?ffmpeg和openCV能实现功能,javaCV如何做到更快、更简单的实现相应的功能?等等一堆实用话题
- ffmpeg 简单功能描述