Bound desktop codec work and drain delayed frames through EOF
This commit is contained in:
1 parent
c02222610b
commit
5ce2877fc0
3 files changed
+146
-54
No files matched your search
@@ -27,6 +27,16 @@ extern "C" {
|
||||
}
|
||||
|
||||
static QList<QByteArray> snapshots;
|
||||
#if defined(TEST_NULL_AUDIO) && defined(HAVE_FFMPEG)
|
||||
static std::atomic<bool> delayedDecoder{false};
|
||||
extern "C" int __real_avcodec_open2(AVCodecContext*, const AVCodec*, AVDictionary**);
|
||||
extern "C" int __wrap_avcodec_open2(AVCodecContext* context, const AVCodec* codec, AVDictionary** options) {
|
||||
if (delayedDecoder && av_codec_is_decoder(codec)) {
|
||||
context->thread_count = 4; context->thread_type = FF_THREAD_FRAME;
|
||||
}
|
||||
return __real_avcodec_open2(context, codec, options);
|
||||
}
|
||||
#endif
|
||||
#ifdef TEST_NULL_AUDIO
|
||||
static std::atomic<ma_device_data_proc> originalAudioCallback{nullptr};
|
||||
static std::atomic<uint64_t> nonzeroSamples{0};
|
||||
@@ -309,6 +319,51 @@ private slots:
|
||||
#endif
|
||||
}
|
||||
|
||||
void delayedDecoderAndShortStreamDrain() {
|
||||
#if defined(TEST_NULL_AUDIO) && defined(HAVE_FFMPEG)
|
||||
const AVCodec* encoder = avcodec_find_encoder_by_name("libx264"); QVERIFY(encoder);
|
||||
AVCodecContext* context = avcodec_alloc_context3(encoder); QVERIFY(context);
|
||||
context->width = 160; context->height = 90; context->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
context->time_base = {1, 25}; context->max_b_frames = 0;
|
||||
AVDictionary* options = nullptr; av_dict_set(&options, "preset", "ultrafast", 0); av_dict_set(&options, "tune", "zerolatency", 0);
|
||||
QCOMPARE(avcodec_open2(context, encoder, &options), 0); av_dict_free(&options);
|
||||
AVFrame* frame = av_frame_alloc(); QVERIFY(frame); frame->width = 160; frame->height = 90; frame->format = context->pix_fmt;
|
||||
QCOMPARE(av_frame_get_buffer(frame, 32), 0);
|
||||
for (int plane = 0; plane < 3; plane++) for (int y = 0; y < (plane ? 45 : 90); y++)
|
||||
memset(frame->data[plane] + y * frame->linesize[plane], plane ? 128 : 80, plane ? 80 : 160);
|
||||
frame->pts = 0; QCOMPARE(avcodec_send_frame(context, frame), 0);
|
||||
AVPacket* packet = av_packet_alloc(); QVERIFY(packet); QCOMPARE(avcodec_receive_packet(context, packet), 0);
|
||||
QByteArray access(reinterpret_cast<const char*>(packet->data), packet->size);
|
||||
av_packet_free(&packet); av_frame_free(&frame); avcodec_free_context(&context);
|
||||
struct Delay { Delay() { delayedDecoder = true; } ~Delay() { delayedDecoder = false; } } delay;
|
||||
for (unsigned count : {3u, 8u}) {
|
||||
QCOMPARE(stream_publish_finish(publisher), STREAM_OK); stream_close(publisher); publisher = nullptr;
|
||||
QCOMPARE(stream_publish_open(inst, group, nullptr, &publisher), STREAM_OK);
|
||||
stream_info info{}; QCOMPARE(stream_get_info(publisher, &info), STREAM_OK); epoch = info.descriptor.source_epoch;
|
||||
StreamPlayerWindow window(group, inst->node_id, epoch, "Delayed decoder"); window.show();
|
||||
QSignalSpy shown(&window, &StreamPlayerWindow::framePresented);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
QByteArray data = i ? access : QByteArray(4, '\0') + access;
|
||||
stream_media_block media{}; media.format = {160, 90, 0, STREAM_MEDIA_H264, 0, 1}; media.video_count = 1;
|
||||
media.video[0] = {i + 1, i * 40000u, (uint32_t)data.size(), 0, (uint32_t)data.size(),
|
||||
(uint8_t)(i ? 0 : STREAM_MEDIA_KEY), reinterpret_cast<const uint8_t*>(data.constData())};
|
||||
uint8_t wire[7345]; size_t length = 0;
|
||||
QCOMPARE(stream_media_encode(&media, wire, sizeof(wire), &length), STREAM_OK);
|
||||
QCOMPARE(stream_publish_block(publisher, wire, length), STREAM_OK); QTest::qWait(i ? 1 : 30);
|
||||
}
|
||||
QTest::qWait(100);
|
||||
if (count == 3) QCOMPARE(shown.count(), 0);
|
||||
else QTRY_VERIFY_WITH_TIMEOUT(shown.count() > 0, 1500);
|
||||
QCOMPARE(stream_publish_finish(publisher), STREAM_OK);
|
||||
QTRY_COMPARE_WITH_TIMEOUT(shown.count(), (int)count, 2000);
|
||||
QTRY_VERIFY_WITH_TIMEOUT(stream_get_info(publisher, &info) == STREAM_OK && info.owners == 1, 2000);
|
||||
window.close(); QTest::qWait(10);
|
||||
}
|
||||
#else
|
||||
QSKIP("Delayed FFmpeg decoder fixture requires Linux and FFmpeg");
|
||||
#endif
|
||||
}
|
||||
|
||||
void finishAndDetachPendingOwner() {
|
||||
QCOMPARE(stream_publish_finish(publisher), STREAM_OK); QTRY_COMPARE(snapshots.last().mid(9), QByteArray("[]"));
|
||||
stream_close(publisher); publisher = nullptr;
|
||||
|
||||
Reference in new issue
Block a user