You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PayloadAPP/Src/VideoGL/savestream.cpp

141 lines
4.7 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "savestream.h"
SaveStream::SaveStream(QObject *parent) : QObject{parent} {}
bool SaveStream::init(AVFormatContext *formatContext,
AVPacketQueueManager *queueManager, int videoIndex) {
// m_inputCodecContex = codecContex;
m_inputFormatContext = formatContext;
// m_saverQueue = queue;
m_queueManager = queueManager;
m_videoIndex = videoIndex;
m_start = openFile();
if (!m_start) {
free();
}
return m_start;
}
void SaveStream::setSaveFileDirPath(QString fileDirPath) {
m_outputDirPath = fileDirPath;
}
void SaveStream::close() {
// QMutexLocker locker(&m_mutex);
m_start = false;
}
void SaveStream::startSaveStream() {
qDebug() << "SaveStreamThreadID:" << QThread::currentThreadId();
if (!m_start) {
return;
}
while (m_start || !m_queueManager->isEmptySaveQueue()) {
AVPacket *inputPacket = m_queueManager->dequeueSavePacket();
if (inputPacket) {
// 由于保存的m_formatContextSave只创建了一个视频流而读取到的图像的流索引不一定为0可能会出现错误【Invalid
// packet stream index: 1】
// 所以这里需要将stream_index指定为和m_formatContextSave中视频流索引相同因为就一个流所以直接设置为0
inputPacket->stream_index = 0;
av_write_frame(m_formatContextSave,
inputPacket); // 将数据包写入输出媒体文件
av_packet_unref(inputPacket);
inputPacket = nullptr;
} else {
QThread::usleep(1000);
}
}
// 写入文件尾
if (m_formatContextSave && m_writeHeader) {
av_write_trailer(m_formatContextSave);
m_writeHeader = false;
}
free();
qDebug() << "视频保存结束!";
emit sendErrorMessageSignal("视频保存结束!",
NotificationType::NOTIFICATION_SUCCESS);
}
bool SaveStream::openFile() {
// QMutexLocker locker(&m_mutex);
QDir dir;
if (!dir.exists(m_outputDirPath)) {
dir.mkdir(m_outputDirPath);
}
QString strName =
QString("/%1.h264")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss"));
strName = m_outputDirPath + strName;
// const AVOutputFormat *ofmt = av_guess_format("mp4", NULL, NULL);
int ret = avformat_alloc_output_context2(
&m_formatContextSave, nullptr, nullptr, strName.toStdString().data());
if (ret < 0) {
showError(ret);
qWarning() << "avformat_alloc_output_context2 Error!";
free();
return false;
}
// m_videoStreamOut->codecpar->codec_tag = 0;
// if (m_formatContextSave->oformat->flags & AVFMT_GLOBALHEADER) {
// m_formatContextSave->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
// // m_videoStreamOut->codecpar->extradata = (uint8_t *)av_malloc(1024);
// // m_videoStreamOut->codecpar->extradata_size = 0;
// }
// 创建并初始化AVIOContext以访问url所指示的资源。
ret = avio_open(&m_formatContextSave->pb, strName.toStdString().data(),
AVIO_FLAG_WRITE);
if (ret < 0) {
showError(ret);
qWarning() << "Open file Error";
free();
return false;
}
// 向媒体文件添加新流
m_videoStreamOut = avformat_new_stream(m_formatContextSave, nullptr);
if (!m_videoStreamOut) {
free();
qWarning() << "Create New Stream Error";
return false;
}
// 拷贝一些参数给codecpar赋值(这里使用编码器上下文进行赋值)
// ret = avcodec_parameters_from_context(m_videoStreamOut->codecpar,
// m_inputCodecContex);
ret = avcodec_parameters_copy(
m_videoStreamOut->codecpar,
m_inputFormatContext->streams[m_videoIndex]->codecpar);
if (ret < 0) {
showError(ret);
free();
qWarning() << "avcodec_parameters_from_context Failed";
return false;
}
// 写入文件头
ret = avformat_write_header(m_formatContextSave, nullptr);
if (ret < 0) {
showError(ret);
free();
qWarning() << "avformat_write_header Error";
return false;
}
m_writeHeader = true;
qDebug() << "保存视频文件初始化成功!";
return true;
}
void SaveStream::free() {
// 关闭文件
if (m_formatContextSave && !(m_formatContextSave->flags & AVFMT_NOFILE)) {
avio_close(m_formatContextSave->pb);
// av_freep(m_videoStreamOut);
// avformat_free_context(m_formatContextSave);
// m_formatContextSave = nullptr;
}
if (m_formatContextSave) {
avformat_free_context(m_formatContextSave);
m_formatContextSave = nullptr;
}
}