145 lines
4.0 KiB
C++
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);
|
|
}
|