Hello libav-users,

With some investigation, i was able to confirm libavformat’s I/O Interrupt 
Callback is not being called by av_read_frame(). Currently, when 
av_read_frame() is called while consuming either USB or IP media streams, if 
the connection is terminated from actions such as the ethernet/usb cable being 
disconnected, av_read_frame() will hang. 

I was able to modify the av_read_frame() routine from libavformat such that the 
same I/O interrupt callback used for other libavformat I/O routines is called 
when reading packets from a stream. It appears to be a minimal change, with no 
API changes. 

The only behavioral change is the I/O Interrupt Callback is called, and it 
respects a positive return value to indicate termination of I/O by 
av_read_frame().

It seems like I am correcting a design oversight: there is a facility for 
library clients to check on pending I/O, that’s the I/O interrupt callback. It 
is being called during other libavformat routines that perform I/O. Yet, for 
the critical step of reading packets from a media stream, it was not being 
called. Finding wrapper logic enabling the hooking in of the interrupt callback 
a mere 3 lines of code, I tried it, built windows x64 and win32 dlls and tested 
with my employer's computer vision system. It does exactly what is needed: when 
reading USB video or IP cameras or Internet streams, "if the cable gets pulled” 
the media library does not hang. Through the interrupt callback, my libavformat 
client code easily implements a timeout, signaling back to libavformat when to 
stop waiting for I/O.

Seeing multiple developers requesting this functionality online, I looked into 
making a patch for submission this back to the ffmpeg developers. It looks like 
the patch submission process is a bit more time consuming than my schedule 
allows. Pretty much because it would require my using git in a manner I am 
unfamiliar. (I barely use git myself, rarely directly.)

I did a git diff to create this, it is the entire change enabling this critical 
functionality:

————————
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 0711310..5971e31 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -1718,6 +1718,12 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
     }
 
     for (;;) {
+       if (ff_check_interrupt(&s->interrupt_callback)) {
+          ret = AVERROR_EXIT;
+          av_log(s, AV_LOG_DEBUG, "interrupted\n");
+          return ret;
+       }
+       
         AVPacketList *pktl = s->internal->packet_buffer;
 
         if (pktl) {

————————

I’ll continue looking into creating a formal submission to the ffmpeg 
developers - BUT if someone more familiar with the process wants to step in, by 
all means. I’ll be fumbling with those steps, under a constrained schedule…

Sincerely,
-Blake Senftner

---> Blake loves the Planet Earth and is proud to display this email with 
Recycled Electrons. <---

_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to