When the button is clicked, I create 16 threads in Qt, and then pass the rtsp data address and the label to be rendered to the process, and then the process does this:
run:
void rtspthread::run()
{
while(!shouldStop){
openRtspStream(rtspUrl.toUtf8().constData(),index);
}
qDebug() << "RTSP stream stopped.";
emit finished();
}
open input stream:
void rtspthread::openRtspStream(const char* rtspUrl,int index)
{
AVDictionary *options = nullptr;
AVFrame *pFrameRGB = nullptr;
uint8_t *pOutBuffer = nullptr;
struct SwsContext *swsContext;
AVFormatContext *pFormatCtx = nullptr;
pFormatCtx = avformat_alloc_context();
av_dict_set(&options, "rtsp_transport", "tcp", 0);
av_dict_set(&options, "maxrate", "4000k", 0);
if (avformat_open_input(&pFormatCtx, rtspUrl, nullptr, &options) != 0) {
printf("Couldn't open stream file.n");
return;
}
if (avformat_find_stream_info(pFormatCtx, NULL)<0)
{
printf("Couldn't find stream information.n");
return;
}
int videoStreamIndex = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex!=-1){
AVStream* videoStream = pFormatCtx->streams[videoStreamIndex];
AVCodecParameters* codecpar = videoStream->codecpar;
const AVCodec* videoCodec = avcodec_find_decoder(codecpar->codec_id);
AVCodecContext* videoCodecContext = avcodec_alloc_context3(videoCodec);
avcodec_parameters_to_context(videoCodecContext,codecpar);
avcodec_open2(videoCodecContext,videoCodec,nullptr);
AVPixelFormat srcPixFmt = videoCodecContext->pix_fmt;
QLabel* label = this->parentWidget->findChild<QLabel*>("videoLabel");
int targetWidth = label->width();
int targetHeight = label->height();
pOutBuffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB32,
videoCodecContext->width,
videoCodecContext->height, 1));
pFrameRGB = av_frame_alloc();
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, pOutBuffer,
AV_PIX_FMT_RGB32, videoCodecContext->width, videoCodecContext->height, 1);
swsContext= sws_getContext(
videoCodecContext->width,videoCodecContext->height,srcPixFmt,
targetWidth, targetHeight,AV_PIX_FMT_RGB32,
SWS_BICUBIC,nullptr,nullptr,nullptr
);
AVPacket packet;
AVFrame* frame = av_frame_alloc();
int frameCounter = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (shouldStop) {
break;
}
if (packet.stream_index == videoStreamIndex) {
int ret = avcodec_send_packet(videoCodecContext,&packet);
int rets = avcodec_receive_frame(videoCodecContext, frame);
if (rets < 0) {
qDebug() << "Error receiving frame from codec context";
}
sws_scale(swsContext, frame->data, frame->linesize, 0, videoCodecContext->height,
pFrameRGB->data, pFrameRGB->linesize);
QImage img(pFrameRGB->data[0], targetWidth, targetHeight,
pFrameRGB->linesize[0], QImage::Format_RGB32);
qDebug() << index;
emit frameReady(img.copy(),index);
QThread::msleep(30); // 控制帧率
}
av_packet_unref(&packet);
}
av_frame_free(&frame);
av_frame_free(&pFrameRGB);
sws_freeContext(swsContext);
avcodec_free_context(&videoCodecContext);
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
}
}
The video is stuck and has snow screen. I want to lower the resolution and reduce the snow screen. The server cannot change the resolution.