ffmpeg视频加水印

int64_t            lastPts;

int64_t            lastDts;

int64_t            lastFrameRealtime;

int64_t            startTime;

AVCodecContext      *outputEncContext;

AVCodecContext      *decoderContext[2];

structSwsContext  *pSwsContext;

AVFilterInOut      *inputs;

AVFilterInOut      *outputs;

AVFilterGraph      *filter_graph;

AVFilterContext    *inputFilterContext[2];

AVFilterContext    *outputFilterContext;

#define SrcWidth1920

#define SrcHeight1080

#define DstWidth640

#define DstHeight480

int64_t            firstPts =AV_NOPTS_VALUE;

constchar          *filter_descr ="overlay=100:100";

intinterrupt_cb(void*ctx)

{

    return 0;

}

+ (int)openInput:(charconst*)fileName inputIndex:(int)inputIndex {

    context[inputIndex] = avformat_alloc_context();

    context[inputIndex]->interrupt_callback.callback = interrupt_cb;

    AVDictionary*format_opts =NULL;


    intret =avformat_open_input(&context[inputIndex], fileName,NULL, &format_opts);

    if(ret <0) {

        returnret;

    }

    ret =avformat_find_stream_info(context[inputIndex],NULL);

    av_dump_format(context[inputIndex],0, fileName,0);

    if(ret >=0) {

        NSLog(@"open input stream successfully!");

    }

    returnret;

}

+ (AVPacket*)readPacketFromSource:(int)inputIndex {

    AVPacket*packet =av_malloc(sizeof(AVPacket));

    av_init_packet(packet);

    intret =av_read_frame(context[inputIndex], packet);

    if(ret >=0) {

        returnpacket;

    }else{

        returnnil;

    }

}

+ (int)openOutput:(charconst*)fileName inputIndex:(int)inputIndex {

    intret =0;

    ret =avformat_alloc_output_context2(&outputContext, NULL, "mpegts", fileName);

    if(ret <0) {

        gotoError;

    }

    ret =avio_open2(&outputContext->pb, fileName,AVIO_FLAG_READ_WRITE,NULL,NULL);

    if(ret <0) {

        gotoError;

    }

    for(inti =0;context[inputIndex]->nb_streams; i++) {

        AVStream *stream = avformat_new_stream(outputContext, outputEncContext->codec);

        stream->codec = outputEncContext;

        if(ret <0) {

            gotoError;

        }

    }

    av_dump_format(outputContext,0, fileName,1);

    ret =avformat_write_header(outputContext, NULL);

    if(ret <0) {

        gotoError;

    }else{

        NSLog(@"open output stream successfully!");

        returnret;

    }


Error:

    if (outputContext) {

        avformat_close_input(&outputContext);

    }

    returnret;

}

+ (void)closeInput:(int)inputIndex {

    if(context[inputIndex]) {

        avformat_close_input(&context[inputIndex]);

    }

}

+ (void)closeOutput {

    if (outputContext) {

        for(inti =0; i nb_streams; i++) {

            AVCodecContext *codecContext = outputContext->streams[i]->codec;

            avcodec_close(codecContext);

        }

        avformat_close_input(&outputContext);

    }

}

+ (int)initEncoderCodecWithWidth:(int)width height:(int)height inputIndex:(int)inputIndex {

    AVCodec *pH264Codec = avcodec_find_encoder(AV_CODEC_ID_H264);

    if(pH264Codec ==NULL) {

        printf("%s","avcodec_find_encoder failed !");

        return-1;

    }

    outputEncContext = avcodec_alloc_context3(pH264Codec);

    outputEncContext->gop_size = 30;

    outputEncContext->has_b_frames = 0;

    outputEncContext->max_b_frames = 0;

    outputEncContext->codec_id = pH264Codec->id;

    outputEncContext->time_base.num = context[inputIndex]->streams[0]->codec->time_base.num;

    outputEncContext->time_base.den = context[inputIndex]->streams[0]->codec->time_base.den;

    outputEncContext->pix_fmt      = *pH264Codec->pix_fmts;

    outputEncContext->width        = width;

    outputEncContext->height        = height;


    outputEncContext->me_subpel_quality = 0;

    outputEncContext->refs = 1;

    outputEncContext->scenechange_threshold = 0;

    outputEncContext->trellis = 0;

    AVDictionary*options =NULL;

    outputEncContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;


    intret =avcodec_open2(outputEncContext, pH264Codec, &options);

    if(ret <0) {

        printf("%s","open codec failed !\n");

        returnret;

    }

    return 1;

}

+ (int)initDecodeCodecWith:(enumAVCodecID)codecId inputIndex:(int)inputIndex {

    AVCodec*deCodec =avcodec_find_decoder(codecId);

    if(!deCodec) {

        return-1;

    }

    decoderContext[inputIndex] =context[inputIndex]->streams[0]->codec;

    if(!decoderContext[inputIndex]) {

        printf("Could not allocate video codec context\n");

        return-1;

    }


    if (deCodec->capabilities & AV_CODEC_CAP_TRUNCATED) {

        decoderContext[inputIndex]->flags|=AV_CODEC_FLAG_TRUNCATED;

    }

    intret =avcodec_open2(decoderContext[inputIndex], deCodec,NULL);

    if(ret <0) {

        printf("%s","open decodec failed !");

    }

    returnret;

}

+ (BOOL)decodeVideo:(AVPacket*)packet frame:(AVFrame*)frame inputIndex:(int)inputIndex {

    intgotFrame =0;

    inthr =avcodec_decode_video2(decoderContext[inputIndex], frame, &gotFrame, packet);

    if(hr >=0&& gotFrame !=0) {

        frame->pts= packet->pts;

        return true;

    }

    return false;

}

+ (int)initInputFilter:(AVFilterInOut*)input fileName:(constchar*)fileName inputIndex:(int)inputIndex {

    charargs[512];

    memset(args,0,sizeof(args));

    AVFilterContext*padFilterContext = input->filter_ctx;


    const AVFilter *filter = avfilter_get_by_name("buffer");

    AVCodecContext*codecContext =context[inputIndex]->streams[0]->codec;


    sprintf(args,sizeof(args),

            "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect+%d/%d",

            codecContext->width,codecContext->height,codecContext->pix_fmt,

            codecContext->time_base.num,codecContext->time_base.den/codecContext->ticks_per_frame,

            codecContext->sample_aspect_ratio.num,codecContext->sample_aspect_ratio.den

            );

    intret =avfilter_graph_create_filter(&inputFilterContext[inputIndex], filter, fileName, args,NULL,filter_graph);

    if(ret <0) {

        returnret;

    }

    ret =avfilter_link(inputFilterContext[inputIndex],0, padFilterContext, input->pad_idx);

    returnret;

}

+ (int)initOutputFilter:(AVFilterInOut*)output filterName:(constchar*)filterName {

    AVFilterContext*padFilterContext = output->filter_ctx;

    const AVFilter *filter = avfilter_get_by_name("buffersink");


    intret =avfilter_graph_create_filter(&outputFilterContext, filter, filterName,NULL,NULL,filter_graph);

    if(ret <0) {

        returnret;

    }

    ret =avfilter_link(padFilterContext, output->pad_idx,outputFilterContext,0);

    returnret;

}

+ (void)freeInout {

    avfilter_inout_free(&inputs->next);

    avfilter_inout_free(&inputs);

    avfilter_inout_free(&outputs);

}

+ (int)_tmain {

    char const      *fileInput1 = [[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp4"] UTF8String];

    char const      *fileInput2 = [[[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"] UTF8String];

    char const      *outputFileName ="/Users/ubaby/Library/Containers/bylh.testFFmpegOS/Data/Documents/test0.mp4";


    av_register_all();

    avfilter_register_all();

    avformat_network_init();

    avdevice_register_all();

    av_log_set_level(AV_LOG_ERROR);


    charconst*fileName = fileInput1;

    for(inti =0; i <2; i++) {

        if(i >0) {

            fileName = fileInput2;

        }

        if([selfopenInput:fileNameinputIndex:i] <0) {

            printf("Open file Input failed !");

            return0;

        }

    }


    for(inti =0; i <2; i++) {

        intret = [selfinitDecodeCodecWith:context[i]->streams[0]->codec->codec_idinputIndex:i];

        if(ret <0) {

            printf("initDecodeCodec failed !");

            return0;

        }

    }


    int ret = [self initEncoderCodecWithWidth:decoderContext[0]->width height:decoderContext[0]->height inputIndex:0];

    if(ret <0) {

        printf("open encoder failed ret is %d",ret);

        printf("initEncoderCodec failed !");

        return0;

    }


    filter_graph = avfilter_graph_alloc();

    if (!filter_graph) {

        printf("graph alloc failed !");

        gotoEnd;

    }


    avfilter_graph_parse2(filter_graph, filter_descr, &inputs, &outputs);

    [self initInputFilter:inputs fileName:"MainFrame" inputIndex:0];

    [self initInputFilter:inputs->next fileName:"OverlayFrame" inputIndex:1];

    [self initOutputFilter:outputs filterName:"output"];

    [self freeInout];


    ret =avfilter_graph_config(filter_graph, NULL);

    if(ret <0) {

        gotoEnd;

    }


    if([selfopenOutput:outputFileNameinputIndex:0] <0) {

        printf("open file Output failed !");

        return0;

    }


    AVFrame*pSrcFrame[2];

    AVFrame*inputFrame[2];

    pSrcFrame[0] =av_frame_alloc();

    pSrcFrame[1] =av_frame_alloc();

    inputFrame[0] =av_frame_alloc();

    inputFrame[1] =av_frame_alloc();


    AVFrame*filterFrame =av_frame_alloc();

    intgot_output =0;

    int64_ttimeRecord =0;

    int64_tfirstPacketTime =0;

    int64_toutLastTime =av_gettime();

    int64_tinLastTime =av_gettime();

    int64_tvideoCount =0;


    while(1) {

        AVPacket*packet = [selfreadPacketFromSource:1];

        BOOLret = [selfdecodeVideo:packetframe:pSrcFrame[1]inputIndex:1];

        if(ret) {

            break;

        }

    }


    while(1) {

        outLastTime =av_gettime();

        AVPacket*packet = [selfreadPacketFromSource:0];

        if(packet) {

            if([selfdecodeVideo:packetframe:pSrcFrame[0]inputIndex:0]) {

                av_frame_ref(inputFrame[0], pSrcFrame[0]);

                if (av_buffersrc_add_frame_flags(inputFilterContext[0], inputFrame[0], AV_BUFFERSRC_FLAG_PUSH) >= 0) {

                    pSrcFrame[1]->pts= pSrcFrame[0]->pts;

                    if (av_buffersrc_add_frame_flags(inputFilterContext[1], pSrcFrame[1], AV_BUFFERSRC_FLAG_PUSH) >= 0) {

                        ret =av_buffersink_get_frame_flags(outputFilterContext, filterFrame,AV_BUFFERSINK_FLAG_NO_REQUEST);

                        if(ret >=0) {

                            AVPacket*pTmpPkt =av_malloc(sizeof(AVPacket));

                            av_init_packet(pTmpPkt);

                            pTmpPkt->data=NULL;

                            pTmpPkt->size=0;

                            ret =avcodec_encode_video2(outputEncContext, pTmpPkt, filterFrame, &got_output);

                            if(ret >=0&& got_output) {

                                intret =av_write_frame(outputContext, pTmpPkt);

                                if(ret <0) {

                                    printf("av_write_frame failed !");

                                    return0;

                                }

                            }

                        }

                        av_frame_free(&filterFrame);

                    }

                }

            }

        }else{

            break;

        }

    }


End:

    [self closeInput:0];

    [self closeInput:1];

    [self closeOutput];

    printf("Transcode file end !");

    return 0;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容