You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.7KB

  1. /*
  2. * FIFO test pseudo-muxer
  3. * Copyright (c) 2016 Jan Sebechlebsky
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with FFmpeg; if not, write to the Free Software * Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <stdlib.h>
  22. #include "libavutil/opt.h"
  23. #include "libavutil/time.h"
  24. #include "libavutil/avassert.h"
  25. #include "avformat.h"
  26. #include "url.h"
  27. /* Implementation of mock muxer to simulate real muxer failures */
  28. #define MAX_TST_PACKETS 128
  29. #define SLEEPTIME_50_MS 50000
  30. #define SLEEPTIME_10_MS 10000
  31. /* Implementation of mock muxer to simulate real muxer failures */
  32. /* This is structure of data sent in packets to
  33. * failing muxer */
  34. typedef struct FailingMuxerPacketData {
  35. int ret; /* return value of write_packet call*/
  36. int recover_after; /* set ret to zero after this number of recovery attempts */
  37. unsigned sleep_time; /* sleep for this long in write_packet to simulate long I/O operation */
  38. } FailingMuxerPacketData;
  39. typedef struct FailingMuxerContext {
  40. AVClass *class;
  41. int write_header_ret;
  42. int write_trailer_ret;
  43. /* If non-zero, summary of processed packets will be printed in deinit */
  44. int print_deinit_summary;
  45. int flush_count;
  46. int pts_written[MAX_TST_PACKETS];
  47. int pts_written_nr;
  48. } FailingMuxerContext;
  49. static int failing_write_header(AVFormatContext *avf)
  50. {
  51. FailingMuxerContext *ctx = avf->priv_data;
  52. return ctx->write_header_ret;
  53. }
  54. static int failing_write_packet(AVFormatContext *avf, AVPacket *pkt)
  55. {
  56. FailingMuxerContext *ctx = avf->priv_data;
  57. int ret = 0;
  58. if (!pkt) {
  59. ctx->flush_count++;
  60. } else {
  61. FailingMuxerPacketData *data = (FailingMuxerPacketData*) pkt->data;
  62. if (!data->recover_after) {
  63. data->ret = 0;
  64. } else {
  65. data->recover_after--;
  66. }
  67. ret = data->ret;
  68. if (data->sleep_time) {
  69. int64_t slept = 0;
  70. while (slept < data->sleep_time) {
  71. if (ff_check_interrupt(&avf->interrupt_callback))
  72. return AVERROR_EXIT;
  73. av_usleep(SLEEPTIME_10_MS);
  74. slept += SLEEPTIME_10_MS;
  75. }
  76. }
  77. if (!ret) {
  78. ctx->pts_written[ctx->pts_written_nr++] = pkt->pts;
  79. av_packet_unref(pkt);
  80. }
  81. }
  82. return ret;
  83. }
  84. static int failing_write_trailer(AVFormatContext *avf)
  85. {
  86. FailingMuxerContext *ctx = avf->priv_data;
  87. return ctx->write_trailer_ret;
  88. }
  89. static void failing_deinit(AVFormatContext *avf)
  90. {
  91. int i;
  92. FailingMuxerContext *ctx = avf->priv_data;
  93. if (!ctx->print_deinit_summary)
  94. return;
  95. printf("flush count: %d\n", ctx->flush_count);
  96. printf("pts seen nr: %d\n", ctx->pts_written_nr);
  97. printf("pts seen: ");
  98. for (i = 0; i < ctx->pts_written_nr; ++i ) {
  99. printf(i ? ",%d" : "%d", ctx->pts_written[i]);
  100. }
  101. printf("\n");
  102. }
  103. #define OFFSET(x) offsetof(FailingMuxerContext, x)
  104. static const AVOption options[] = {
  105. {"write_header_ret", "write_header() return value", OFFSET(write_header_ret),
  106. AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
  107. {"write_trailer_ret", "write_trailer() return value", OFFSET(write_trailer_ret),
  108. AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
  109. {"print_deinit_summary", "print summary when deinitializing muxer", OFFSET(print_deinit_summary),
  110. AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
  111. {NULL}
  112. };
  113. static const AVClass failing_muxer_class = {
  114. .class_name = "Fifo test muxer",
  115. .item_name = av_default_item_name,
  116. .option = options,
  117. .version = LIBAVUTIL_VERSION_INT,
  118. };
  119. AVOutputFormat ff_fifo_test_muxer = {
  120. .name = "fifo_test",
  121. .long_name = NULL_IF_CONFIG_SMALL("Fifo test muxer"),
  122. .priv_data_size = sizeof(FailingMuxerContext),
  123. .write_header = failing_write_header,
  124. .write_packet = failing_write_packet,
  125. .write_trailer = failing_write_trailer,
  126. .deinit = failing_deinit,
  127. .priv_class = &failing_muxer_class,
  128. .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH,
  129. };