HxNvr/HxRtspBase/HxVideoLiveStream.cpp
2024-04-17 15:31:43 +08:00

145 lines
4.0 KiB
C++

#include "HxVideoLiveStream.h"
HxVideoLiveStream::HxVideoLiveStream(int millisecond) : HxThread(millisecond) { }
HxVideoLiveStream::~HxVideoLiveStream() {}
void HxVideoLiveStream::set_url(QString url, ConnectType type) { this->url = url; m_type = type;}
void HxVideoLiveStream::set_uuid(QString uuid) { this->uuid = uuid; }
void HxVideoLiveStream::set_status_callback(OnVideoStatusCallback callback) { status_callback = callback; }
void HxVideoLiveStream::set_stream_callback(OnVideoStreamCallback callback) { stream_callback = callback; }
ConnectionStatus HxVideoLiveStream::connect()
{
pts = dts = -1;
m_pause = false;
int error = 0;
AVDictionary *avdic = nullptr;
/* 减少卡顿或者花屏现象,相当于增加或扩大了缓冲区,给予编码和发送足够的时间 */
av_dict_set(&avdic, "buffer_size", "1024000", 0);
// /* 减少采集缓存 */
// av_dict_set(&avdic, "preset", "fast", 0);
// av_dict_set(&avdic, "tune", "zerolatency", 0);
// /* 减少音频采集sampels数量 */
// av_dict_set(&avdic, "audio_buffer_size","30", 0);
// av_dict_set(&avdic, "stimeout", "500000", 0);
// av_dict_set(&avdic, "max_delay", "500000", 0);
av_dict_set(&avdic, "rtsp_transport", "tcp", 0);
avformat_network_init();
ifmt_ctx = avformat_alloc_context();
error = avformat_open_input(&ifmt_ctx, url.toUtf8().data(), nullptr, &avdic);
av_dict_free(&avdic);
if (error != 0)
{
avformat_free_context(ifmt_ctx);
return ConnectionStatus::Disconnected;
}
if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0)
{
avformat_close_input(&ifmt_ctx);
avformat_free_context(ifmt_ctx);
return ConnectionStatus::Disconnected;
}
av_dump_format(ifmt_ctx, 0, url.toUtf8().data(), 0);
int index = -1;
for (uint i = 0; i < ifmt_ctx->nb_streams; i++)
{
if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
index = static_cast<int>(i);
HxTrace::debug_write_line("rtsp info", QString("%1 width=%2, height=%3").arg(url)
.arg(ifmt_ctx->streams[index]->codecpar->width)
.arg(ifmt_ctx->streams[index]->codecpar->height));
break;
}
}
if (index == -1 ||
ifmt_ctx->streams[index]->codecpar->width == 0 ||
ifmt_ctx->streams[index]->codecpar->height == 0)
{
avformat_close_input(&ifmt_ctx);
avformat_free_context(ifmt_ctx);
return ConnectionStatus::Disconnected;
}
/* 这里获取的是微秒,需要转成秒 */
duartion = ifmt_ctx->duration / 1000000;
return status = ConnectionStatus::Connected;
}
void HxVideoLiveStream::pause(bool status) { m_pause = status; }
void HxVideoLiveStream::position(int value) { av_seek_frame(ifmt_ctx, -1, value * 1000 * 1000, AVSEEK_FLAG_BACKWARD); }
void HxVideoLiveStream::action()
{
if (status != ConnectionStatus::Connected && m_type == LiveStream)
{
status_callback(uuid, ConnectionStatus::Connecting);
status = connect();
status_callback(uuid, status);
if (status != ConnectionStatus::Connected)
{
msleep(1000);
}
}
else
{
if(m_pause)
return;
AVPacket packet;
if (av_read_frame(ifmt_ctx, &packet) >= 0)
{
if (stream_callback)
stream_callback(uuid, HxVideoFrame(QDateTime::currentDateTime(), ifmt_ctx, &packet));
}
else
{
if(m_type == LiveStream)
continue_with();
}
av_packet_unref(&packet);
}
}
void HxVideoLiveStream::continue_with()
{
status = ConnectionStatus::Disconnected;
if (ifmt_ctx != nullptr)
{
avformat_close_input(&ifmt_ctx);
avformat_free_context(ifmt_ctx);
ifmt_ctx = nullptr;
}
status_callback(uuid, status);
}