Created
February 8, 2018 15:34
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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