Skip to content

Instantly share code, notes, and snippets.

@bsenftner
Created February 8, 2018 15:34
Show Gist options
  • Save bsenftner/ba3d493fa36b0b201ffd995e8c2c60a2 to your computer and use it in GitHub Desktop.
Save bsenftner/ba3d493fa36b0b201ffd995e8c2c60a2 to your computer and use it in GitHub Desktop.
libav modification of libavformat/utils.c providing support for unexpected stream termination in live RTSP or similar video streams.
// Inside the file libavformat/utils.c is the routine "int av_read_frame(AVFormatContext *s, AVPacket *pkt)", one of the key routines
// used to play video streams through FFMPEG's libav. This routine does not handle the situation when a live stream terminates
// unexpectedly, such as the unplugging of a network connection, power loss to a camera, or other reasons an established connection
// would unexpectedly stop delivering packets.
// Below is the beginning of av_read_frame() up to and a bit past the three added lines necessary to support calling of the installed
// avformat interrupt callback. The conventional libav behavior is to call the avformat interrupt callback while establishing a new
// connection with a live stream. It is not called while the stream is playing, therefore no opportunity is provided to the client
// software to recognise unexpected stream termination.
// The three lines are added to the code pasted below. They should be easy to identify:
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
const int genpts = s->flags & AVFMT_FLAG_GENPTS;
int eof = 0;
int ret;
AVStream *st;
if (!genpts) {
ret = s->internal->packet_buffer
? read_from_packet_buffer(&s->internal->packet_buffer,
&s->internal->packet_buffer_end, pkt)
: read_frame_internal(s, pkt);
if (ret < 0)
return ret;
goto return_packet;
}
for (;;) {
//
// Blake Senftner modification for CyberExtruder see libav-user 2/1/2017
if (ff_check_interrupt(&s->interrupt_callback)) {
ret = AVERROR_EXIT;
av_log(s, AV_LOG_DEBUG, "interrupted\n" );
return ret;
}
// end Blake modification
//
AVPacketList *pktl = s->internal->packet_buffer;
if (pktl) {
AVPacket *next_pkt = &pktl->pkt;
if (next_pkt->dts != AV_NOPTS_VALUE) {
int wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;
// last dts seen for this stream. if any of packets following
// current one had no dts, we will set this to AV_NOPTS_VALUE.
int64_t last_dts = next_pkt->dts;
av_assert2(wrap_bits <= 64);
while (pktl && next_pkt->pts == AV_NOPTS_VALUE) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment