Allocate padded RGB frames for FFmpeg video conversion

This commit is contained in:
evgeny committed 2026-10-17 01:28:04 +02:00
1 parent 88e3e27145
commit f81b93ad0d
3 files changed
+39 -4

No files matched your search

+2 -1
View File
@@ -1,4 +1,5 @@
#include "call_video_decoder.h"
#include "video_frame_image.h"
#include "debug_config.h"
#include "../../../src/call/call_video_bitstream.h"
#include <QTransform>
@@ -88,7 +89,7 @@ bool CallVideoDecoder::decode(const call_video_frame& f, QImage& image) {
valid = valid && (m->codec->profile == profile || (f.format.codec == CALL_VIDEO_H264
&& f.format.profile == CALL_VIDEO_BASELINE && m->codec->profile == AV_PROFILE_H264_BASELINE));
if (valid) {
QImage output(decoded->width, decoded->height, QImage::Format_RGB888);
QImage output = video_frame_image(decoded->width, decoded->height);
m->scale = sws_getCachedContext(m->scale, decoded->width, decoded->height, AV_PIX_FMT_YUV420P,
decoded->width, decoded->height, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
if (!m->scale || output.isNull()) valid = false;
+4 -3
View File
@@ -1,5 +1,6 @@
#include "streamplayer_window.h"
#include "videoplayer_window.h"
#include "video_frame_image.h"
#include "sound_manager.h"
#include "../transport/stream_bridge.h"
#include <QVBoxLayout>
@@ -178,8 +179,8 @@ void StreamPlayerWindow::tick() {
}
if (!image.isNull()) {
m_render->setFrame(image); m_status->setText(text("Live"));
if (first) DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop first frame id=%llu %dx%d", (unsigned long long)p.id,
image.width(), image.height());
if (first) DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop first frame id=%llu %dx%d RGB_stride=%lld",
(unsigned long long)p.id, image.width(), image.height(), (long long)image.bytesPerLine());
emit framePresented();
}
if (finished) { m_status->setText(text("Stream ended")); m_audio.close(); m_timer.stop(); }
@@ -284,7 +285,7 @@ void StreamPlayerWindow::decode() {
if (pts < p.clock(nowUs()) - 100000) { discarded++; continue; } }
converter = sws_getCachedContext(converter, frame->width, frame->height, (AVPixelFormat)frame->format,
frame->width, frame->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
QImage image(frame->width, frame->height, QImage::Format_RGB888);
QImage image = video_frame_image(frame->width, frame->height);
if (!converter || image.isNull()) { fail(text("Stream video conversion failed")); p.running = false; return; }
uint8_t* destination[] = {image.bits(), nullptr, nullptr, nullptr};
int strides[] = {(int)image.bytesPerLine(), 0, 0, 0};
+33
View File
@@ -0,0 +1,33 @@
/* RGB888 для sws_scale: FFmpeg выделяет выровненные строки и запас для SIMD.
* QImage разделяет буфер без копирования; последний владелец освобождает AVFrame. */
#pragma once
#ifdef HAVE_FFMPEG
#include <QImage>
#include "debug_config.h"
extern "C" {
#include <libavutil/frame.h>
}
inline QImage video_frame_image(int width, int height) {
AVFrame* frame = av_frame_alloc();
if (!frame) {
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "video RGB frame allocation failed size=%dx%d", width, height); return {};
}
frame->format = AV_PIX_FMT_RGB24; frame->width = width; frame->height = height;
int result = av_frame_get_buffer(frame, 32);
if (result < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "video RGB buffer allocation failed size=%dx%d result=%d", width, height, result);
av_frame_free(&frame); return {};
}
QImage image(frame->data[0], width, height, frame->linesize[0], QImage::Format_RGB888, [](void* owner) {
auto* frame = static_cast<AVFrame*>(owner); av_frame_free(&frame);
}, frame);
if (image.isNull()) {
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "video RGB image initialization failed size=%dx%d stride=%d", width, height, frame->linesize[0]);
av_frame_free(&frame); return {};
}
DEBUG_TRACE(DEBUG_CATEGORY_VIDEO, "video RGB buffer allocated size=%dx%d stride=%d alignment=32", width, height, frame->linesize[0]);
return image;
}
#endif