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;
}
网友评论