ios ffmpeg 保存mp4
废话不说,直接上代码:
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相关推荐
- ffmpeg 保存MP4后前端无法打开,并且缺失宽高等基础信息
最近采用ffmpeg做一个流媒体服务器,当录像的时候,前端反应无法打开mp4,仔细一看文件也没有缩略图,通过VLC发现可以打开播放,然后用ffmpeg命令查看了一下格式如下: ffprobe -sho ...
- linux python保存mp4
解决 python调用OpenCV 保存视频时使用"avc1"格式出现# Could not find encoder for codec id 27: Encoder not f ...
- Android直播开发之旅(17):使用FFmpeg提取MP4中的H264和AAC
最近在开发中遇到了一个问题,即无法提取到MP4中H264流的关键帧进行处理,且保存到本地的AAC音频也无法正常播放.经过调试分析发现,这是由于解封装MP4得到的H264和AAC是ES流,它们缺失解码时 ...
- 【Opencv基础学习】 VideoWriter打开本地摄像头并保存mp4格式视频
你好! 这是我第一次用CSDN编写博客.该专栏博客主要来记录学习使用Opencv过程中所遇到的问题及解决方案. 这篇博客主要记录了使用Opencv打开本地摄像头录制视频,并保存为*.mp4文件格式视频 ...
- python视频格式转换命令_python怎么实现文件格式的转换 批处理使用ffmpeg为mp4批量加入字幕...
ffmpeg怎么批量处理任意类型的视频文件 如何用python实现视频关键帧提取并保存为图片?我想要和你一直在一起.一直到世界的终结.可以看到花开的微笑. import cv2vc = cv2.Vid ...
- H.264 媒体流 AnnexB 和 AVCC 格式分析 及 FFmpeg 解析mp4的H.264码流方法
H264码流分两种组织方式,一种是AnnexB格式,一种是AVCC格式. 作者:码农小明 来源:https://blog.csdn.net/shaosunrise/article/details/12 ...
- python3保存mp4 avi转mp4
win10系统, opencv4.5版本,读取mp4,保存mp4,示例代码,测试ok. opencv4.2以上版本,写完图片, 不调用release, 1)调用break, 2)或者release() ...
- 转: FFMpeg 封装MP4 文件
FFmpeg 封装MP4文件的一个例子 项目中用到FFmpeg 将IP摄像头的视频流的保存MP4文件的.之前的大哥将它先存成了H264文件,然后又调用FFMpeg的命令行去实现转码为MP4.感觉 ...
- ffmpeg 从mp4上提取H264的nalu
1.获取数据 ffmpeg读取mp4中的H264数据,并不能直接得到NALU,文件中也没有储存0x00000001的分隔符.下面这张图为packet.data中的数据 从图中可以发现,packet中的 ...
最新文章
- 第8章6节MonkeyRunner启动运行过程-启动Monkey 4
- 2006年世界杯小组赛日程表
- 隐藏Apache Nginx PHP版本号
- Java字节码进制转换
- java多线程:线程体往外抛出异常的处理机制实践
- 怎样知道邮箱的端口_AllenNLP源码拓展——训练结束向邮箱发邮件
- 7-57 又来一个上三角数字三角形 (10 分)
- 电脑上怎么配置mysql数据库服务器_Mysql数据库服务器安装与配置详解教程
- Django学习(第四天:ORMModel)
- [USACO 4.2] 完美的牛栏
- 今天开始学C#.NET
- 数据库逻辑删除的sql语句_通过数据库的眼睛查询sql的逻辑流程
- Java中map关于putAll()和“=”的区别
- 一杯水怎么测试_每滴都是“芯”鲜好水,碧然德新款净水器实测
- springboot application.properties server.port配置小问题
- android 灰色向白色渐变,iPhone-iOS的白色到透明渐变层为灰色
- OpenLayers 绘制,选中,鼠标悬浮
- 置信区间的置信区间_什么是置信区间,为什么人们使用它们?
- gb2312的6763个汉字
- python线程池原理及使用
热门文章
- html5添加随机率,HTML5 canvas 绘制随机曲线 并实现放大功能
- 扬州智能机器人项目股票代码_特种智能机器人项目落户前湾新区
- #修改margin_springboot+jpa+tymeleaf实现信息修改功能
- easyui前端实现多选框_前端:Element UI 多选框组用法笔记
- jquery mobile app案例_讲座预告 | 运动app内的个人成就、运动轨迹和社交分享对体能提升的长期效应研究...
- mysql 包括冒号_hibernate中SQL包含冒号
- java域对象_javaWeb域对象
- 别再说程序员不懂时尚
- TiDB 数据库的 4 大应用场景分析
- 传统网站性能优化的三种手段