废话不说,直接上代码:

header写入成功:

-(void) init_mp4saving:(AVFormatContext*) pFormatCtx videoStreamin:(int) videoStream savenamein:(NSString *)savename {
    
    i_video_stream=pFormatCtx->streams[videoStream];
    int ret;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSCalendar *curCalendar = [NSCalendar currentCalendar];
    NSUInteger unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents *dateComponents = [curCalendar components:unitFlags fromDate:[NSDate date]];
    movBasePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    filePath = [movBasePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%ld-%ld-%ld.mp4",(long)dateComponents.hour, (long)dateComponents.minute, (long)dateComponents.second ]];
    [fileManager createFileAtPath:filePath contents:nil attributes:nil];
    const char *out_filename = [filePath UTF8String];//URL 路径
    //    av_register_all();//注册所有容器格式和CODEC
    avformat_alloc_output_context2(&outfmt_ctx, NULL, "mp4", out_filename);// 初始化一个用于输出的AVFormatContext结构体
    if (!outfmt_ctx) {
        NSLog(@ "Could not create output context\n");
    }
    outFormat = outfmt_ctx->oformat;
    AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);//查找对应的解码器
    AVStream *out_stream = avformat_new_stream(outfmt_ctx, codec);//创建输出码流的AVStream
    if (!out_stream){
        NSLog(@ "Failed allocating output stream\n");
    }
    out_Cdc_ctx=out_stream->codec;
    out_Cdc_ctx->pix_fmt = i_video_stream->codec->pix_fmt;
    int FPS=30;
    out_Cdc_ctx = out_stream->codec;
    out_Cdc_ctx->extradata = i_video_stream->codec->extradata;
    out_Cdc_ctx->extradata_size = i_video_stream->codec->extradata_size;
    out_Cdc_ctx->bit_rate = 16*1000;
    out_Cdc_ctx->codec_id = i_video_stream->codec->codec_id;
    out_Cdc_ctx->codec_type = i_video_stream->codec->codec_type;
    out_Cdc_ctx->time_base.num =1;// i_video_stream->time_base.num;
    out_Cdc_ctx->time_base.den =25;// i_video_stream->time_base.den;
    out_Cdc_ctx->time_base = (AVRational){1,FPS};
    fprintf(stderr, "time_base.num = %d time_base.den = %d\n", out_Cdc_ctx->time_base.num, out_Cdc_ctx->time_base.den);
    out_Cdc_ctx->width = i_video_stream->codec->width;
    out_Cdc_ctx->height = i_video_stream->codec->height;
    out_Cdc_ctx->pix_fmt = i_video_stream->codec->pix_fmt;
    NSLog(@"mp4save width:%d height:%d pix_fmt: %d", out_Cdc_ctx->width, out_Cdc_ctx->height, out_Cdc_ctx->pix_fmt);
    out_Cdc_ctx->flags = i_video_stream->codec->flags;
    out_Cdc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
    out_Cdc_ctx->me_range = i_video_stream->codec->me_range;
    out_Cdc_ctx->max_qdiff = i_video_stream->codec->max_qdiff;
    out_Cdc_ctx->qmin = i_video_stream->codec->qmin;
    out_Cdc_ctx->qmax = i_video_stream->codec->qmax;
    out_Cdc_ctx->qcompress = i_video_stream->codec->qcompress;
    //    ret = avcodec_copy_context(out_stream->codec, avcodec_alloc_context3(codec));//拷贝输入视频码流的AVCodecContex的数值t到输出视频的AVCodecContext。
    //    if (ret < 0)
    //    {
    //        NSLog(@ "Failed to copy context from input to output stream codec context\n");
    //    }
    //    out_stream->codec->pix_fmt = AV_PIX_FMT_YUV420P;//支持的像素格式
    //    out_stream->codec->flags = CODEC_FLAG_GLOBAL_HEADER;
    //    out_stream->codec->width = i_video_stream->codec->width;
    //    out_stream->codec->height = i_video_stream->codec->height;
    //    out_stream->time_base=i_video_stream->time_base;
        out_stream->codec->time_base = (AVRational){1,FPS};
        out_stream->codec->gop_size = FPS;
    //    out_stream->codec->bit_rate = 16*1000;
    //    out_stream->codec->codec_tag = 0;
    out_stream->codec->time_base = (AVRational){1,FPS};
    if (outfmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
    {
        out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }
    //    AVBitStreamFilterContext \*avFilter = av_bitstream_filter_init("h264_mp4toannexb");
    //    out_stream->codec->extradata_size = size;
    //    out_stream->codec->extradata = (uint8_t \*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
    //输出一下格式------------------
    av_dump_format(outfmt_ctx, 0, out_filename, 1);
    if (!(outFormat->flags & AVFMT_NOFILE))
    {
                ret = avio_open(&outfmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
                if (ret < 0)
                {
                    NSLog(@ "Could not open output file %@", out_filename);
                }
    }
    //    //写文件头(Write file header)
    AVDictionary* opt = NULL;
    //av_dict_set(&opt, "video_track_timescale", "25", 0);
    av_dict_set(&opt, "timescale", "25", 0);
    av_dict_set(&opt, "video_timescale", "25", 0);
    av_dict_set(&opt, "track_timescale", "25", 0);
        ret = avformat_write_header(outfmt_ctx, &opt);
        if (ret < 0)
        {
            NSLog(@ "Error occurred when opening output file\n");
        }
    //    input_video_stream = *(pFormatCtx->streams[videoStream]);
    //o_video_stream->time_base.num = 1;
    // o_video_stream->time_base.den = 25;
   }

保存帧和尾的代码:

bool isIDR = true;
               unsigned char c[5] ={ 0x00, 0x00, 0x00, 0x01, 0x67};
               int n=0;
               for( n =0 ;n<5;n++){
                   if(vp.data[n]!=c[n]){
                       isIDR=false;break;
                   }
               }
               if(!isIDR){
                   if(record_status==1){
//                       sprintf(savename,"/sdcard/record_%d.mp4", ++record_num);
                        savename = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/Movie2.mp4"];
                       [self init_mp4saving:pFormatCtx videoStreamin:videoStream savenamein:savename ];
                       last_pts = 0;
                       last_dts = 0;
                       finished = 0;
                       NSLog(@"record_status ok  : record_status = %d \n",record_status);
                       record_status=2;
                   }
               }
               
               if(record_status==2){
                   frame_num++;
                   NSLog(@"record_status ok  : record_status = %d \n",record_status);
                   NSLog(@"frame index %d\n", frame_num);
                   packet.flags |= AV_PKT_FLAG_KEY;
                   packet.pts += last_pts;
//                   if (pCodecCtx->coded_frame->pts != AV_NOPTS_VALUE){
//                       packet.pts= av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, _videoStream->time_base);
//                       NSLog(@"frame index2 %d packet->pts %d\n", frame_num,packet.pts);
//                   }
                   packet.dts += last_dts;
                   packet.stream_index = 0;
                   packet.duration=1;
                   
                   av_interleaved_write_frame(outfmt_ctx, &packet);
                   if(frame_num>200){
                       record_status=3;
                   }
               }  else if(record_status==3){
                   // avformat_close_input(&i_fmt_ctx);
                   
                   NSLog(@"av_write_trailer!!!!!!!!!!  \n" );
                   av_write_trailer(outfmt_ctx);
                   
                   NSLog(@" avcodec_close!!!!!!!!  \n" );
                   avcodec_close(outfmt_ctx->streams[0]->codec);
                   
                   av_freep(&outfmt_ctx->streams[0]->codec);
                   av_freep(&outfmt_ctx->streams[0]);
                   avio_close(outfmt_ctx->pb);
                   av_free(outfmt_ctx);
                   record_status = 0;
                   NSLog(@"record_end\n");
               }

ios ffmpeg 保存mp4相关推荐

  1. ffmpeg 保存MP4后前端无法打开,并且缺失宽高等基础信息

    最近采用ffmpeg做一个流媒体服务器,当录像的时候,前端反应无法打开mp4,仔细一看文件也没有缩略图,通过VLC发现可以打开播放,然后用ffmpeg命令查看了一下格式如下: ffprobe -sho ...

  2. linux python保存mp4

    解决 python调用OpenCV 保存视频时使用"avc1"格式出现# Could not find encoder for codec id 27: Encoder not f ...

  3. Android直播开发之旅(17):使用FFmpeg提取MP4中的H264和AAC

    最近在开发中遇到了一个问题,即无法提取到MP4中H264流的关键帧进行处理,且保存到本地的AAC音频也无法正常播放.经过调试分析发现,这是由于解封装MP4得到的H264和AAC是ES流,它们缺失解码时 ...

  4. 【Opencv基础学习】 VideoWriter打开本地摄像头并保存mp4格式视频

    你好! 这是我第一次用CSDN编写博客.该专栏博客主要来记录学习使用Opencv过程中所遇到的问题及解决方案. 这篇博客主要记录了使用Opencv打开本地摄像头录制视频,并保存为*.mp4文件格式视频 ...

  5. python视频格式转换命令_python怎么实现文件格式的转换 批处理使用ffmpeg为mp4批量加入字幕...

    ffmpeg怎么批量处理任意类型的视频文件 如何用python实现视频关键帧提取并保存为图片?我想要和你一直在一起.一直到世界的终结.可以看到花开的微笑. import cv2vc = cv2.Vid ...

  6. H.264 媒体流 AnnexB 和 AVCC 格式分析 及 FFmpeg 解析mp4的H.264码流方法

    H264码流分两种组织方式,一种是AnnexB格式,一种是AVCC格式. 作者:码农小明 来源:https://blog.csdn.net/shaosunrise/article/details/12 ...

  7. python3保存mp4 avi转mp4

    win10系统, opencv4.5版本,读取mp4,保存mp4,示例代码,测试ok. opencv4.2以上版本,写完图片, 不调用release, 1)调用break, 2)或者release() ...

  8. 转: FFMpeg 封装MP4 文件

    FFmpeg 封装MP4文件的一个例子    项目中用到FFmpeg 将IP摄像头的视频流的保存MP4文件的.之前的大哥将它先存成了H264文件,然后又调用FFMpeg的命令行去实现转码为MP4.感觉 ...

  9. ffmpeg 从mp4上提取H264的nalu

    1.获取数据 ffmpeg读取mp4中的H264数据,并不能直接得到NALU,文件中也没有储存0x00000001的分隔符.下面这张图为packet.data中的数据 从图中可以发现,packet中的 ...

最新文章

  1. 第8章6节MonkeyRunner启动运行过程-启动Monkey 4
  2. 2006年世界杯小组赛日程表
  3. 隐藏Apache Nginx PHP版本号
  4. Java字节码进制转换
  5. java多线程:线程体往外抛出异常的处理机制实践
  6. 怎样知道邮箱的端口_AllenNLP源码拓展——训练结束向邮箱发邮件
  7. 7-57 又来一个上三角数字三角形 (10 分)
  8. 电脑上怎么配置mysql数据库服务器_Mysql数据库服务器安装与配置详解教程
  9. Django学习(第四天:ORMModel)
  10. [USACO 4.2] 完美的牛栏
  11. 今天开始学C#.NET
  12. 数据库逻辑删除的sql语句_通过数据库的眼睛查询sql的逻辑流程
  13. Java中map关于putAll()和“=”的区别
  14. 一杯水怎么测试_每滴都是“芯”鲜好水,碧然德新款净水器实测
  15. springboot application.properties server.port配置小问题
  16. android 灰色向白色渐变,iPhone-iOS的白色到透明渐变层为灰色
  17. OpenLayers 绘制,选中,鼠标悬浮
  18. 置信区间的置信区间_什么是置信区间,为什么人们使用它们?
  19. gb2312的6763个汉字
  20. python线程池原理及使用

热门文章

  1. html5添加随机率,HTML5 canvas  绘制随机曲线 并实现放大功能
  2. 扬州智能机器人项目股票代码_特种智能机器人项目落户前湾新区
  3. #修改margin_springboot+jpa+tymeleaf实现信息修改功能
  4. easyui前端实现多选框_前端:Element UI 多选框组用法笔记
  5. jquery mobile app案例_讲座预告 | 运动app内的个人成就、运动轨迹和社交分享对体能提升的长期效应研究...
  6. mysql 包括冒号_hibernate中SQL包含冒号
  7. java域对象_javaWeb域对象
  8. 别再说程序员不懂时尚
  9. TiDB 数据库的 4 大应用场景分析
  10. 传统网站性能优化的三种手段