











一、概述
保存网络流为mp4存储到本地是一个通用的并且常用的需求,例如在视频监控、网络直播领域会根据不同级别以及重要程度保存媒体流到本地一定的时间,有些要求一周,有些要求半年、一年乃至几年的都有。
如何保存这些流就成为了关键。当然有些需求还涉及到了转码,但是本节只讲如何将流原封不动的保存下来,不考虑转码。转码的需求将在后续的文章中给出具体的方案。
本节会模拟一个视频流,即输入一个mp4文件,通过解封装拿到AVPacket,并将AVPacket保存到本地的其他目录,从而达到模拟的效果。
主要步骤:
二、代码示例
//1.创建解封装上下文,并打开文件 AVFormatContext* ic = nullptr; int re = avformat_open_input(&ic, this->srcFilePath.toStdString().c_str(), NULL, NULL); if (re != 0) { PrintError(re, "avformat_open_input"); return; }
//2.发现媒体信息流 re = avformat_find_stream_info(ic, NULL); if (re < 0) { PrintError(re, "avformat_find_stream_info"); return; }
//3.分别找到音频流以及视频流 AVStream* vs = nullptr; AVStream* as = nullptr; for (int i = 0;i < ic->nb_streams;i++) { if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { as = ic->streams[i]; } else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { vs = ic->streams[i]; } }
///4.创建封装器上下文 AVFormatContext* oc = nullptr; re = avformat_alloc_output_context2(&oc, NULL, NULL, this->dstFilePath.toStdString().c_str()); if (re < 0) { PrintError(re, "avformat_alloc_output_context2"); return; }
//添加音频流以及视频流 auto ovs = avformat_new_stream(oc, NULL); auto oas = avformat_new_stream(oc, NULL);
//将输入流的编解码参数,复制到输出流中 if (vs) { ovs->time_base = vs->time_base; avcodec_parameters_copy(ovs->codecpar, vs->codecpar); } if (as) { oas->time_base = as->time_base; avcodec_parameters_copy(oas->codecpar, as->codecpar); }
//打开输出流 re = avio_open(&oc->pb, this->dstFilePath.toStdString().c_str(), AVIO_FLAG_WRITE); if (re < 0) { PrintError(re, "avio_open"); return; }
//写入文件头 re = avformat_write_header(oc, NULL); if (re < 0) { PrintError(re, "avformat_write_header"); return; }
while (isRunning) { //解封装 re = av_read_frame(ic, &pkt); if (re != 0) { PrintError(re, "av_read_frame"); break; }//写入音视频帧,此方法会自动清理AVPacket re = av_interleaved_write_frame(oc, &pkt); if (re != 0) { PrintError(re, "av_interleaved_write_frame"); } }
//写入尾部 re = av_write_trailer(oc); if (re != 0) { PrintError(re, "av_write_trailer"); }
//关闭解封装输入上下文 avformat_close_input(&ic); //关闭写入IO avio_closep(&oc->pb); //释放申请的输出解封装上下文 avformat_free_context(oc); oc = nullptr;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。