#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(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); }