|
http://bbs.csdn.net/topics/390722822?page=1
最近改了个视频解码编码的小程序,能得到最后的结果,但是内存老是释放不了,希望高手指点!附代码如下: const char *input_file_name="/users/sj/desktop/HH_videoTransform2/input.mov"; av_register_all();//注册库中所有可用的文件格式和编码器 AVFormatContext *ic; //输入文件处理部分 ic=avformat_alloc_context(); if(av_open_input_file(&ic,input_file_name,NULL,0,NULL)!=0) { printf("can't open the file %s\n",input_file_name); exit(1); }//打开输入文件 if(av_find_stream_info(ic)<0) { printf("can't find suitable codec parameters\n"); exit(1); }//取出流信息 dump_format(ic,0,input_file_name,0);//列出输入文件的相关流信息 int i; int videoindex=-1; int audioindex=-1; for(i=0;i<ic->nb_streams;i++) { if(ic->streams->codec->codec_type==CODEC_TYPE_VIDEO) { videoindex=i; //printf("video\n"); } else if(ic->streams->codec->codec_type==CODEC_TYPE_AUDIO) { //printf("audio\n"); audioindex=i; } } if(videoindex==-1) { printf("can't find video stream\n"); exit(1); }//没有找到视频流 AVCodecContext *vCodecCtx; vCodecCtx=ic->streams[videoindex]->codec;//取得视频流编码上下文指针 AVCodec *vCodec; vCodec=avcodec_find_decoder(vCodecCtx->codec_id); if(vCodec==NULL) { printf("can't find suitable video decoder\n"); exit(1); }//找到合适的视频解码器 if(avcodec_open(vCodecCtx,vCodec)<0) { printf("can't open the video decoder\n"); exit(1); }//打开该视频解码器 if(audioindex==-1) { printf("can't find audio stream\n"); // exit(1); }//没有找到音频流 //下面为输出文件处理部分 const char *output_file_name="/users/sj/desktop/HH_videoTransform2/output.mov"; AVOutputFormat *fmt; AVFormatContext *oc; AVCodecContext *oVcc/*,*oAcc*/; AVCodec *oVc/*,*oAc*/; AVStream *video_st/*,*audio_st*/; AVFrame *oVFrame/*,*oAFrame*/; // double video_pts; oVFrame=avcodec_alloc_frame(); fmt=av_guess_format(NULL,output_file_name,NULL); if(!fmt) { printf("could not deduce output format from outfile extension\n"); exit(0); }//判断是否可以判断输出文件的编码格式 oc=avformat_alloc_context(); if(!oc) { printf("Memory error\n"); exit(0); } oc->oformat=fmt; strcpy(oc->filename, output_file_name); video_st=av_new_stream(oc,0); if(!video_st) { printf("could not alloc video stream\n"); exit(0); } video_st->duration=ic->streams[videoindex]->duration; if (fmt->video_codec != CODEC_ID_NONE) { oVcc=avcodec_alloc_context(); oVcc=video_st->codec; oVcc->codec_id=fmt->video_codec; oVcc->codec_type=CODEC_TYPE_VIDEO; oVcc->bit_rate=vCodecCtx->bit_rate; oVcc->width=vCodecCtx->width; oVcc->height=vCodecCtx->height; oVcc->time_base=vCodecCtx->time_base; oVcc->gop_size=vCodecCtx->gop_size; //oVcc->pix_fmt=vCodecCtx->pix_fmt; oVcc->pix_fmt=vCodecCtx->pix_fmt; oVcc->max_b_frames=vCodecCtx->max_b_frames; video_st->r_frame_rate=ic->streams[videoindex]->r_frame_rate; if (oVcc->codec_id == CODEC_ID_MPEG2VIDEO) { oVcc->max_b_frames = 2; } if (oVcc->codec_id == CODEC_ID_MPEG1VIDEO) { oVcc->mb_decision = 2; } if (!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp")) { oVcc->flags |= CODEC_FLAG_GLOBAL_HEADER; } } if (av_set_parameters(oc, NULL) < 0) { printf( "Invalid output format parameters\n"); exit(0); }//设置必要的输出参数 strcpy(oc->title,ic->title); strcpy(oc->author,ic->author); strcpy(oc->copyright,ic->copyright); strcpy(oc->comment,ic->comment); strcpy(oc->album,ic->album); oc->year=ic->year; oc->track=ic->track; strcpy(oc->genre,ic->genre); dump_format(oc,0,output_file_name,1);//列出输出文件的相关流信息 // oVc=avcodec_find_encoder(CODEC_ID_MPEG4); oVc=avcodec_find_encoder(oVcc->codec_id); if(!oVc) { printf("can't find suitable video encoder\n"); exit(0); }//找到合适的视频编码器 if(avcodec_open(oVcc,oVc)<0) { printf("can't open the output video codec\n"); exit(0); }//打开视频编码器 if(url_exist(output_file_name)) { printf("the output file name %s has exist,please select other\n",output_file_name); exit(0); }//判断该输出文件是否已经存在 if (!(oc->flags & AVFMT_NOFILE)) { if(url_fopen(&oc->pb,output_file_name,URL_WRONLY)<0) { printf("can't open the output file %s\n",output_file_name); exit(0); }//打开输出文件 } if(!oc->nb_streams) { fprintf(stderr,"output file dose not contain any stream\n"); exit(0); }//查看输出文件是否含有流信息 if(av_write_header(oc)<0) { fprintf(stderr, "Could not write header for output file\n"); exit(1); } AVPacket packet; int out_size; uint8_t *video_outbuf; int video_outbuf_size; video_outbuf_size=vCodecCtx->width*vCodecCtx->height*3/2+100000; video_outbuf= (unsigned char *) malloc(video_outbuf_size); int got_picture=0; int len; int frame_index=0,ret; int packet_count=0; int skipped_frame=0; //int packet_audio=0; while(av_read_frame(ic,&packet)>=0)//从输入文件中读取一个包 { if(packet.stream_index==videoindex)//判断是否为当前视频流中的包 { NSLog(@"%d packet decoded",packet_count); len=avcodec_decode_video2(vCodecCtx, oVFrame, &got_picture, &packet); if(len<0) { printf("Error while decoding\n"); exit(0); } if(got_picture)// { fflush(stdout); oVFrame->pts=av_rescale_q(packet.pts, ic->streams[videoindex]->time_base, video_st->time_base); oVFrame->pict_type=0; out_size = avcodec_encode_video(oVcc, video_outbuf, video_outbuf_size, oVFrame); if (out_size > 0) { AVPacket pkt; av_init_packet(&pkt); if(oVcc->coded_frame && oVcc->coded_frame->key_frame) pkt.flags |= PKT_FLAG_KEY; pkt.flags = packet.flags; pkt.stream_index= video_st->index; pkt.data= video_outbuf; pkt.size= out_size; ret=av_write_frame(oc, &pkt); } skipped_frame++; } else { ret=av_write_frame(oc, &packet); } frame_index++; if(ret!=0) { printf("while write video frame error\n"); exit(0); } packet_count++; } else if(packet.stream_index==audioindex) { if (av_write_frame(oc, &packet) != 0) { fprintf(stderr, "Error while writing audio frame\n"); exit(1); } } av_free_packet(&packet); } av_write_trailer(oc); for(i = 0; i < oc->nb_streams; i++) { av_freep(&oc->streams->codec); av_freep(&oc->streams); } url_fclose(oc->pb); av_free(oVFrame); avcodec_close(vCodecCtx); av_close_input_file(ic); av_freep(ic); av_free(oc); av_free(oVc); av_free(oVcc); av_free(oAc); av_free(oAcc); NSLog(@"transform end"); } 为什么我已经都av_free了,但是ic 、oc、oAcc,oAc,oVcc,oVc都还是在内存中呢,是不是释放内存的方法不对? |