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