Rtsp拉流录制MP4
来源:互联网 发布:卖假货的淘宝店 编辑:程序博客网 时间:2024/05/16 10:53
最近做了个项目,是rtsp拉流保存成MP4,由于之前已经完成本地录制,所以只要稍微改一下就可以了,顺便写个博客。
平台:ARM+linux
用到的库:ffmpeg
一、首先是拉流
拉流直接使用av_read_frame直接就可以。然后分辩其stream_index即可,video_stream_idx和audio_stream_idx是初始化input确定的。
我这里直接保存入队列,防止IO操作时间太长,阻塞拉流。
while(1){ AVPacket pkt; av_read_frame(Gparg->ifmt_ctx, &pkt); if(pkt.stream_index==Gparg->video_stream_idx) { video_Enqueue(&pkt,Gparg); } else if(pkt.stream_index==Gparg->audio_stream_idx) { audio_Enqueue(&pkt,Gparg); } av_packet_unref(&pkt);}
二、入队出队
保存只需要pts、dts、size、stream_index、data这些数据,根据我的需求,我没有使用ffmpeg里复制AVPacket的函数,所以我就直接复制和拷贝了。
这里我使用的是循环队列,循环队列的好处是有一大块连续的空间,释放的时候比链表方便,操作也方便。
入队关键代码:
queue->avPacket[queue->rear]->size=pkt->size;queue->avPacket[queue->rear]->stream_index=pkt->stream_index;memcpy(queue->avPacket[queue->rear]->data,pkt->data,pkt->size);
由于我用循环队列,所以直接指向就行了。这里注意,我传进来的是AVPacket** pkt,这样指向地址才行的通。
出队关键代码:
*pkt=queue->avPacket[queue->front];
三、录制
我是用H264+aac完成的MP4录制,直接复用即可。所以出队的AVPacket直接写入就行了。
本来是视频和音频一起写的,也就是计算视频和音频的pts差值,那个小就写入哪个。但是发现当视频数据大量涌入,而视频pts也很大,就会造成,写很多音频才写一次视频,所以为了避免这个,就分成2个线程写了,记得用线程锁。
录制关键代码:
for(;;){ if(Gparg->g_AVStopGetStream)//当退出时。这里作flush用,把队列里的剩余都写出来 { while(!av_queue_isEmpty(v_queue)) { ret=video_Dequeue(v_queue,&v_pkt,Gparg); WriteVideo(v_pkt,Gparg); } break; } else { { v_lastpts=v_pts; ret=video_Dequeue(v_queue,&v_pkt,Gparg); if(ret==0&&(v_pkt != NULL)&& (v_pkt->size> 0)) { v_lastpts=v_pkt->pts; WriteVideo(v_pkt,Gparg); } v_pts=v_lastpts; } }}
由于write_frame会清空v_pkt的指向,所以重新用了一个pkt。
WriteVideo函数关键代码:
AVPacket pkt ; av_init_packet(&pkt); pkt.pts=v_pkt->pts; pkt.dts=v_pkt->dts; pkt.data=v_pkt->data; pkt.size=v_pkt->size; pkt.stream_index=v_pkt->stream_index; pkt.flags|=AV_PKT_FLAG_KEY; pthread_mutex_lock (&Gparg->mutex); int ret= av_interleaved_write_frame(Gparg->ofmt_ctx, &pkt); pthread_mutex_unlock (&Gparg->mutex); av_packet_unref(&pkt); if (ret < 0) { SAMPLE_PRT( " end Error while writing video frame: %s\n", av_err2str(ret)); return ret; } return HI_SUCCESS;
四、额外几个Tips
1、获取inputfile的音视频格式信息
在ifmt_ctx->streams[i]->codecpar 里,而帧数是在ifmt_ctx->streams[i]里的avg_frame_rate
2、有时视频播放时间不对,需要设置
AVDictionary *opt=NULL;av_dict_set_int(&opt,"video_track_timescale",90000,0);ret=avformat_write_header(Gparg->ofmt_ctx,&opt);
后面如果有修改的还会再补充
- Rtsp拉流录制MP4
- 将RTSP流录制为mp4文件
- 将RTSP流录制为mp4文件
- 【rtsp录制器】testRTSPClient+mp4v2录制mp4(h264+aac)
- ffmpeg API录制rtsp视频流
- ffmpeg API录制rtsp视频流
- FFmpeg API录制rtsp视频流
- ffmpeg API录制rtsp视频流
- ffmpeg API录制rtsp视频流
- EasyStream系列7之录制rtsp流
- rtsp录制成mp4
- rtsp 保存MP4
- mp4 , rtsp --> rtmp
- mpv2 mp4录制
- freeswith 录制 MP4格式视频
- 修改live555支持mpeg2ts RTSP拉流,附代码
- 通过rtsp获取H264裸流并保存到mp4文件
- ffmpeg学习(二) 通过rtsp获取H264裸流并保存到mp4文件
- java读取类路径的配置文件问题
- mvcc
- 掌握USB/HDMI/MHL/DP验证规范 高速接口传输一次上手
- vin码(车架号)识别解析系统
- JavaBean & super & this
- Rtsp拉流录制MP4
- 关于json的几个方法
- java导出多个exce或者1个exell
- Ubuntu安装UFW防火墙以及常用操作
- 生成函数(母函数)入门详解
- JZOJ 100035. 【NOIP2017提高A组模拟7.10】区间
- kali4.9 64位系统2017版本安装w3af详细步骤以及遇到的问题解决方法
- window系统安装mysql数据库解压缩版
- DirectX11(五)