[Ffmpeg-devel] HTTP probing issue...

Ryan Martell rdm4
Tue Feb 20 22:27:07 CET 2007


On Feb 20, 2007, at 2:47 PM, Klaas-Pieter Vlieg wrote:

> Hi
>
>> From: Ryan Martell [mailto:rdm4 at martellventures.com]
>> Sent: 20 February 2007 21:29
>>
>> I have a weird bug, and I'm not exactly sure how to fix it.
>>
>> Essentially, I am adding an asx demuxer to ffmpeg, to support
>> asx files (which are used to redirect to mms streams, among
>> other things).  These are essentially an xml file, with video
>> resources to play in order contained inside them.
>>
>> To do this, I modified libavformat/utils.c, along the lines
>> of the http redirector.  I know it's not optimal, but it's
>> working within the existing structure.  This worked until I
>> updated to the latest source base yesterday.
>>
>> The problem now is that when probing, it needs to open the
>> file and read data.  The probesize is 2048, which is fine.
>> It downloads the entire asx file, which is only 218 bytes.
>> It then hangs, waiting for more data.  I narrowed it down to
>> tcp_read, in libavformat/tcp.c.
>>
>> The problem is that the first time, it returns the entire file.
>> Thereafter, when it is called, there is no data to read on
>> the connection (as it's all been sent), so select returns 0.
>> No data will ever be sent, and select is not returning the FD
>> as being set, so it will never trigger the close connection
>> state.  If I curl the same url, it returns a 218 byte file,
>> then quits, so I suspect that the connection is being closed
>> on the remote end (although have not confirmed it).
>>
>> I'm also not sure why this has become broken- did the old
>> version of the http.c code use the Content-Length: field to
>> determine the length of the file, and catch EOF at that level?
>>
> Try this: add a sleep(1); at line 99 in http.c
> Works for me.

Not sure if I'm following it.  It does the open fine (which is where  
line 99 is in http.c).  My problem is that when it's trying to read  
the probe size in libavformat/utils.c, it's not hitting EOF.   
Instead, it's just waiting for more data (after it's read  
everything....)

Here's my debug strings:

About to check format...  (in libavformat/utils.c)
Result Format: <null> (<null>)...
Done to check format...
**** Must open file: 1 Format: <null> (in libavformat/utils.c)
tcp_read asked for 1024 bytes (probe size)
about to call recv asking for 1024 bytes (Errno: 36)
tcp_read returning 489 bytes errno: 36 (this was the complete file +  
tcp header)
**** Opened
**** Probing size: 2048
in get_buffer 2048 (filling the ByteIOContext for http.c)
in get_buffer len: 0
in fill_buffer
reading packet: 32768
http_read asked for 32768
Reading from buffer
http_read returning 217 (this was the entire file, sans the header)
reading packet result: 217: 32768
after fill_buffer: 217
in get_buffer len: 217
in get_buffer len: 0
in fill_buffer
reading packet: 32768 (Now it hasn't realized it's EOF, so it's  
asking again...)
http_read asked for 32768
Calling url_read for 32768 bytes
tcp_read asked for 32768 bytes
select returning 0 (There was no data, and there never will be....)
select returning 0
select returning 0
select returning 0
select returning 0
....
....

When I hit 'q', it then interrupts the http.c stuff, and recognizes  
the file format, but quits out.


My code from tcp.c (to show av_log's):

static int tcp_read(URLContext *h, uint8_t *buf, int size)
{
     TCPContext *s = h->priv_data;
     int len, fd_max, ret;
     fd_set rfds;
     struct timeval tv;

     av_log(NULL, AV_LOG_DEBUG, "tcp_read asked for %d bytes\n", size);
     for (;;) {
         if (url_interrupt_cb())
             return AVERROR(EINTR);
         fd_max = s->fd;
         FD_ZERO(&rfds);
         FD_SET(s->fd, &rfds);
         tv.tv_sec = 0;
         tv.tv_usec = 100 * 1000;
         ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
         if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
             av_log(NULL, AV_LOG_DEBUG, "about to call recv asking  
for %d bytes (Errno: %d)\n", size, errno);
             len = recv(s->fd, buf, size, 0);
             av_log(NULL, AV_LOG_DEBUG, "tcp_read returning %d bytes  
errno: %d\n", len, errno);
             if (len < 0) {
                 if (errno != EINTR && errno != EAGAIN)
                     return AVERROR(errno);
             } else return len;
         } else if (ret < 0) {
             av_log(NULL, AV_LOG_DEBUG, "select returning -1\n");
             return -1;
         } else if(ret==0)
         {
             av_log(NULL, AV_LOG_DEBUG, "select returning 0\n");
         }
     }
}

I could add length checking to http.c, now that the Content-Length is  
getting parsed out, but that isn't a required header field in HTTP  
(though I suspect it's pretty standard nowadays).  I'm not sure why  
this is broken now but it wasn't before, unless probesize increased  
drastically since December...

Thanks!
-Ryan




More information about the ffmpeg-devel mailing list