Hi, libavformat currently doesn't provide any mechanism for detecting when a substream is no longer present but the stream as a whole is otherwise OK. Your best guess is to check when you last got any frames on it, which tends to work for video and audio but not for substreams that sometimes spend a long amount of time without presenting anything, like subtitles.
I've attached my first attempt at a detection mechanism, implemented as an AVSTREAM_EVENT_FLAG. Depending on the demultiplexer it's either raised when the substream carrier has died (e.g. if you have one pipe per substream and that one in particular broke), or if its presence wasn't detected during the last call to av_read_frame. I've added it to the MPEG-TS demultiplexer as that's where it itches, but I could see it being somewhat relevant for other formats as well. Does this sound useful to anyone but me? If yes, can you think of a better way of exposing this functionality? Regards, John Högberg
From 0f4183bf6f942df7fe7813e002b2697928acf937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <[email protected]> Date: Thu, 7 May 2015 14:24:27 +0200 Subject: [RFC] Add a stream event for detecting carrier loss. AVSTREAM_EVENT_FLAG_NO_CARRIER: depending on the carrier type of the stream, it either indicates that no carrier was detected for the stream during the latest call, or that the carrier was lost. The former case is distinct from there being no data, and is intended to be used for the detection of a common error in in MPEG-TS; the lack of presence of a stream defined in the headers. --- libavformat/avformat.h | 21 +++++++++++++++++++++ libavformat/mpegts.c | 6 ++++++ libavformat/utils.c | 12 +++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index aa11cff..78cbe83 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -814,6 +814,27 @@ typedef struct AVStream { */ int event_flags; #define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata. +#define AVSTREAM_EVENT_FLAG_NO_CARRIER 0x0002 ///< For constant carrier types, the carrier was lost during the + /// call. For intermittent carrier types, no carrier for this + /// stream was present during the call. + + /** + * The kind of carrier this stream has. Used to determine how the NO_CARRIER + * event should be raised and cleared. + * + * Constant means that the stream is presumed to be present, and the event + * will be raised whenever the underlying demultiplexer has determined that + * this specific stream has lost its carrier. This is the default behavior. + * + * Intermittent means that the stream is presumed to be missing, and the + * event will be cleared when a carrier is present on this specific stream. + * + * demuxing/muxing: set by libavformat, must not be modified by the caller. + */ + enum AVStreamCarrierType { + AVSTREAM_CARRIER_TYPE_CONSTANT = 0, + AVSTREAM_CARRIER_TYPE_INTERMITTENT, + } carrier_type; /***************************************************************** * All fields below this line are not part of the public API. They diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 8f61f17..6217e5e 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -652,6 +652,7 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, st->codec->codec_type = AVMEDIA_TYPE_DATA; st->codec->codec_id = AV_CODEC_ID_NONE; st->need_parsing = AVSTREAM_PARSE_FULL; + st->carrier_type = AVSTREAM_CARRIER_TYPE_INTERMITTENT; pes->st = st; pes->stream_type = stream_type; @@ -840,6 +841,10 @@ static int mpegts_push_data(MpegTSFilter *filter, av_log(pes->stream, AV_LOG_TRACE, "pid=%x pes_code=%#x\n", pes->pid, code); + if(pes->st) { + pes->st->event_flags &= ~AVSTREAM_EVENT_FLAG_NO_CARRIER; + } + if ((pes->st && pes->st->discard == AVDISCARD_ALL && (!pes->sub_st || pes->sub_st->discard == AVDISCARD_ALL)) || @@ -1507,6 +1512,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type default: break; } + *pp = desc_end; return 0; } diff --git a/libavformat/utils.c b/libavformat/utils.c index 18cd0d7..72a4ad9 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -971,7 +971,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) int av_read_frame(AVFormatContext *s, AVPacket *pkt) { const int genpts = s->flags & AVFMT_FLAG_GENPTS; - int eof = 0; + int eof = 0, i; if (!genpts) return s->internal->packet_buffer @@ -979,6 +979,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) &s->internal->packet_buffer_end, pkt) : read_frame_internal(s, pkt); + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + + if(st->carrier_type == AVSTREAM_CARRIER_TYPE_INTERMITTENT) { + st->event_flags |= AVSTREAM_EVENT_FLAG_NO_CARRIER; + } + } + for (;;) { int ret; AVPacketList *pktl = s->internal->packet_buffer; @@ -2559,6 +2567,8 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) st->info->fps_first_dts = AV_NOPTS_VALUE; st->info->fps_last_dts = AV_NOPTS_VALUE; + st->carrier_type = AVSTREAM_CARRIER_TYPE_CONSTANT; + s->streams[s->nb_streams++] = st; return st; } -- 2.1.0
_______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
