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;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咏窿,一起剝皮案震驚了整個濱河市植影,隨后出現(xiàn)的幾起案子府树,更是在濱河造成了極大的恐慌呼寸,老刑警劉巖右犹,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桑包,死亡現(xiàn)場離奇詭異湾趾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)唯鸭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門须蜗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事明肮×馀” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵晤愧,是天一觀的道長大莫。 經(jīng)常有香客問我蛉腌,道長官份,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任烙丛,我火速辦了婚禮舅巷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘河咽。我一直安慰自己钠右,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布忘蟹。 她就那樣靜靜地躺著飒房,像睡著了一般。 火紅的嫁衣襯著肌膚如雪媚值。 梳的紋絲不亂的頭發(fā)上狠毯,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音褥芒,去河邊找鬼嚼松。 笑死,一個胖子當(dāng)著我的面吹牛锰扶,可吹牛的內(nèi)容都是我干的献酗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼坷牛,長吁一口氣:“原來是場噩夢啊……” “哼罕偎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起京闰,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤锨亏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忙干,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體器予,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年捐迫,在試婚紗的時候發(fā)現(xiàn)自己被綠了乾翔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖反浓,靈堂內(nèi)的尸體忽然破棺而出萌丈,到底是詐尸還是另有隱情,我是刑警寧澤雷则,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布辆雾,位于F島的核電站,受9級特大地震影響月劈,放射性物質(zhì)發(fā)生泄漏度迂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一猜揪、第九天 我趴在偏房一處隱蔽的房頂上張望惭墓。 院中可真熱鬧,春花似錦而姐、人聲如沸腊凶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钧萍。三九已至,卻和暖如春政鼠,著一層夾襖步出監(jiān)牢的瞬間风瘦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工缔俄, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留弛秋,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓俐载,卻偏偏與公主長得像蟹略,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子遏佣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容