Guard RGB conversion bounds and use padded frames in file playback
This commit is contained in:
1 parent
f81b93ad0d
commit
64bbbdc631
3 files changed
+76
-7
No files matched your search
@@ -1,5 +1,6 @@
|
||||
#include <QCoreApplication>
|
||||
#include "videoplayer_engine.h"
|
||||
#include "video_frame_image.h"
|
||||
#include "sound_manager.h"
|
||||
#include "../../lib/debug_config.h"
|
||||
|
||||
@@ -200,14 +201,20 @@ void Worker::run() {
|
||||
|
||||
int gen = epoch->loadRelaxed();
|
||||
auto emitFrame = [&](AVFrame* fr) {
|
||||
if (fr->pts == AV_NOPTS_VALUE) return; /* кадр без pts ломает очередь */
|
||||
QImage img(vw, vh, QImage::Format_RGB888);
|
||||
uint8_t* dst[1] = { img.bits() };
|
||||
int dstStride[1] = { (int)img.bytesPerLine() };
|
||||
sws_scale(sws, fr->data, fr->linesize, 0, vh, dst, dstStride);
|
||||
if (fr->pts == AV_NOPTS_VALUE) return true; /* кадр без pts ломает очередь */
|
||||
QImage img = video_frame_image(vw, vh);
|
||||
if (img.isNull()) { worker_fail(this, QCoreApplication::translate("ChatGui", "alloc failed")); return false; }
|
||||
uint8_t* dst[4] = { img.bits(), nullptr, nullptr, nullptr };
|
||||
int dstStride[4] = { (int)img.bytesPerLine(), 0, 0, 0 };
|
||||
int rows = sws_scale(sws, fr->data, fr->linesize, 0, vh, dst, dstStride);
|
||||
if (rows != vh) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "VideoEngine: RGB conversion failed size=%dx%d stride=%d rows=%d", vw, vh, dstStride[0], rows);
|
||||
worker_fail(this, QCoreApplication::translate("ChatGui", "Video frame conversion failed")); return false;
|
||||
}
|
||||
qint64 ptsMs = av_rescale_q(fr->pts, vst->time_base, AVRational{1, 1000});
|
||||
buffered->fetchAndAddRelaxed(1);
|
||||
emit frameDecoded(img, ptsMs, gen);
|
||||
return true;
|
||||
};
|
||||
|
||||
bool eof = false;
|
||||
@@ -232,7 +239,7 @@ void Worker::run() {
|
||||
int ret = av_read_frame(fmt, pkt);
|
||||
if (ret < 0) {
|
||||
avcodec_send_packet(vdec, nullptr);
|
||||
while (avcodec_receive_frame(vdec, frame) == 0) emitFrame(frame);
|
||||
while (avcodec_receive_frame(vdec, frame) == 0) if (!emitFrame(frame)) { cleanup(); return; }
|
||||
eof = true;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "VideoEngine: decode finished");
|
||||
emit finished();
|
||||
@@ -240,7 +247,7 @@ void Worker::run() {
|
||||
}
|
||||
if (pkt->stream_index == vidx) {
|
||||
avcodec_send_packet(vdec, pkt);
|
||||
while (avcodec_receive_frame(vdec, frame) == 0) emitFrame(frame);
|
||||
while (avcodec_receive_frame(vdec, frame) == 0) if (!emitFrame(frame)) { cleanup(); return; }
|
||||
}
|
||||
av_packet_unref(pkt);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user