Rtsp拉流录制MP4

最近做了个项目,是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);

后面如果有修改的还会再补充

### RK3588 RTSP Pull Stream and Store Implementation 在RK3588平台上实现通过RTSP协议取视频并进行存储的过程可以分为几个主要部分:安装必要的工具和库、配置GStreamer管道以RTSP以及设置文件存储机制。 #### 工具与环境准备 为了支持RTSP取和处理,在RK3588设备上需要先安装GStreamer框架及其相关插件。可以通过以下命令完成基本依赖项的安装: ```bash sudo apt-get update &amp;&amp; sudo apt-get upgrade -y sudo apt-get install gstreamer1.0-tools gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \ gstreamer1.0-plugins-ugly gstreamer1.0-libav -y ``` 如果需要更高级的功能或者特定版本的支持,则可能还需要手动编译最新的GStreamer源码[^1]。 对于某些特殊需求,比如硬件加速编码/解码功能,建议参考官方文档或社区资源来定制化构建FFmpeg或GStreamer带有的硬解码库支持[^3]。 #### GStreamer Pipeline Design for RTSP Streaming 设计用于接收RTSP并将数据保存至本地磁盘的GStreamer pipeline时,通常会采用`rtspsrc`作为源头节点,并连接其他组件完成后续操作。下面给出了一条典型的pipeline定义示例: ```bash gst-launch-1.0 rtspsrc location=rtsp://<your_rtsp_url> ! decodebin ! videoconvert ! filesink location=output_video.mp4 ``` 这条指令的作用是从指定地址获取RTSP(`location=<your_rtsp_url>`),经过初步解析后交给`decodebin`自动匹配合适的解码方式;接着利用`videoconvert`确保输出格式兼容性良好,最后写入名为`output_video.mp4`的文件当中[^4]。 需要注意的是实际部署过程中可能会遇到各种各样的问题,例如网络延迟影响稳定性、不同摄像头厂商间协议差异等等情况都需要额外考虑解决办法[^2]。 #### 存储优化策略 当面对长时间连续录制场景下产生的海量数据量时,单纯依靠单个大尺寸文件显然不是最佳实践。因此推荐采取分片形式管理录像资料——即每隔固定时间段创建新的目标文件继续追加新内容进去。修改后的脚本如下所示: ```bash gst-launch-1.0 rtspsrc name=src src.location=rtsp://<your_rtsp_url> \ ! queue leaky=no max-size-buffers=0 max-size-bytes=0 max-size-time=0 \ ! rtph264depay ! h264parse config-interval=-1 ! mp4mux fragment-duration=5000 \ ! multifilesink location="recorded_%05d.mp4" ``` 这里引入了`multifilesink`元素配合参数设定实现了按需切分逻辑(每五秒切换一次)。同时保留原始H.264封装结构减少码开销提升效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值