您的位置:首页 > 其它

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;

    

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ffmpeg
相关文章推荐