[FFmpeg-devel,v3,11/11] avformat/fifo: Add test for nonblocking mode

Submitted by sebechlebskyjan@gmail.com on Aug. 11, 2016, 12:58 p.m.

Details

Message ID 1470920290-4356-1-git-send-email-sebechlebskyjan@gmail.com
State New
Headers show

Commit Message

sebechlebskyjan@gmail.com Aug. 11, 2016, 12:58 p.m.
From: Jan Sebechlebsky <sebechlebskyjan@gmail.com>

Signed-off-by: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
---
 No changes since the last version of the patch, just rebased 
 because of changes in previous fate test patch.

 libavformat/tests/fifo_muxer.c | 139 +++++++++++++++++++++++++++++++++++++++++
 tests/ref/fate/fifo-muxer-tst  |   5 ++
 2 files changed, 144 insertions(+)

Patch hide | download patch | download mbox

diff --git a/libavformat/tests/fifo_muxer.c b/libavformat/tests/fifo_muxer.c
index d6ce85d..deb2656 100644
--- a/libavformat/tests/fifo_muxer.c
+++ b/libavformat/tests/fifo_muxer.c
@@ -336,6 +336,137 @@  fail:
     return ret;
 }
 
+static int retry_write_frame(AVFormatContext *oc, AVPacket *pkt, int max_retries)
+{
+    int ret = 0, retry_count = 0;
+    do {
+        ret = av_write_frame(oc, pkt);
+        if (ret == AVERROR(EAGAIN)) {
+            av_usleep(SLEEPTIME_10_MS);
+            retry_count++;
+        }
+    } while ( ret == AVERROR(EAGAIN) && retry_count < max_retries);
+    return ret;
+}
+
+static int retry_write_trailer(AVFormatContext *oc, int max_retries)
+{
+    int ret = 0, retry_count = 0;
+    do {
+        ret = av_write_trailer(oc);
+        if (ret == AVERROR(EAGAIN)) {
+            av_usleep(SLEEPTIME_10_MS);
+            retry_count++;
+        }
+    } while (ret == AVERROR(EAGAIN) && retry_count < max_retries);
+    return ret;
+}
+
+static int fifo_nonblock_test(AVFormatContext *oc, AVDictionary **opts,
+                              const FailingMuxerPacketData *pkt_data)
+{
+    int ret = 0, i;
+    AVPacket pkt;
+
+    av_init_packet(&pkt);
+
+    oc->flags |= AVFMT_FLAG_NONBLOCK;
+
+    ret = avformat_write_header(oc, opts);
+    if (ret) {
+        fprintf(stderr, "Unexpected write_header failure: %s\n",
+                av_err2str(ret));
+        return ret;
+    }
+
+    for (i = 0; i < 16; i++ ) {
+        ret = prepare_packet(&pkt, pkt_data, i);
+        if (ret < 0) {
+            fprintf(stderr, "Failed to prepare test packet: %s\n",
+                    av_err2str(ret));
+            goto fail;
+        }
+        ret = retry_write_frame(oc, &pkt, 100);
+        av_packet_unref(&pkt);
+        if (ret < 0)
+            break;
+    }
+
+    if (ret) {
+        fprintf(stderr, "Unexpected write_packet error: %s\n", av_err2str(ret));
+        goto fail;
+    }
+
+    ret = retry_write_trailer(oc, 100);
+    if (ret == AVERROR(EAGAIN)) {
+        fprintf(stderr, "write_trailer() operation timeout\n");
+        goto fail;
+    } else if (ret < 0)
+        fprintf(stderr, "Unexpected write_trailer error: %s\n", av_err2str(ret));
+
+    return ret;
+fail:
+    avformat_write_abort(oc);
+    return ret;
+}
+
+static int fifo_nonblock_abort_test(AVFormatContext *oc, AVDictionary **opts,
+                                    const FailingMuxerPacketData *pkt_data)
+{
+    int ret = 0, i;
+    AVPacket pkt;
+    int64_t start_time, end_time, duration;
+
+    av_init_packet(&pkt);
+
+    oc->flags |= AVFMT_FLAG_NONBLOCK;
+
+    ret = avformat_write_header(oc, opts);
+    if (ret) {
+        fprintf(stderr, "Unexpected write header failure: %s\n",
+                av_err2str(ret));
+        goto fail;
+    }
+
+    av_assert0(pkt_data->sleep_time > 0);
+
+    start_time = av_gettime_relative();
+    for (i = 0; i < 16; i++ ) {
+        ret = prepare_packet(&pkt, pkt_data, i);
+        if (ret < 0) {
+            fprintf(stderr, "Failed to prepare test packet: %s\n",
+                    av_err2str(ret));
+            goto fail;
+        }
+        ret = retry_write_frame(oc, &pkt, 100);
+        av_packet_unref(&pkt);
+        if (ret < 0)
+            break;
+    }
+
+    if (ret) {
+        fprintf(stderr, "Unexpected write_packet error: %s\n", av_err2str(ret));
+        goto fail;
+    }
+
+    avformat_write_abort(oc);
+
+    end_time = av_gettime_relative();
+    duration = end_time - start_time;
+
+    if (duration > (16*pkt_data->sleep_time)/2 ) {
+        fprintf(stderr, "Aborting output took too much time: %u us,"
+                " expected time if not aborted %u us\n",
+                (unsigned) duration, 16*pkt_data->sleep_time);
+        ret = AVERROR(ETIMEDOUT);
+    }
+
+    return ret;
+fail:
+    avformat_write_abort(oc);
+    return ret;
+}
+
 typedef struct TestCase {
     int (*test_func)(AVFormatContext *, AVDictionary **,const FailingMuxerPacketData *pkt_data);
     const char *test_name;
@@ -423,6 +554,14 @@  const TestCase tests[] = {
         {fifo_overflow_drop_test, "overflow with packet dropping", "queue_size=3:drop_pkts_on_overflow=1",
          0, 0, 0, {0, 0, SLEEPTIME_50_MS}},
 
+        /* Simple test of nonblocking mode, the consumer should receive all the packets. */
+        {fifo_nonblock_test, "nonblocking mode test", "queue_size=3",
+         1, 0, 0, {0, 0, SLEEPTIME_10_MS}},
+
+        /* Test of terminating fifo muxer with av_abort_format() */
+        {fifo_nonblock_abort_test, "abort in nonblocking mode", "queue_size=16",
+         0, 0, 0, {0, 0, SLEEPTIME_50_MS}},
+
         {NULL}
 };
 
diff --git a/tests/ref/fate/fifo-muxer-tst b/tests/ref/fate/fifo-muxer-tst
index ca7e294..1c18887 100644
--- a/tests/ref/fate/fifo-muxer-tst
+++ b/tests/ref/fate/fifo-muxer-tst
@@ -9,3 +9,8 @@  pts seen nr: 15
 pts seen: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
 overflow without packet dropping: ok
 overflow with packet dropping: ok
+flush count: 0
+pts seen nr: 16
+pts seen: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+nonblocking mode test: ok
+abort in nonblocking mode: ok