Flash Media Server/FFmpeg Annoyance #2: Clients not allowed to broadcast message.

By Brian Lesser
November 5, 2011

Last year Ryerson University had a booth at NAB and I was part of the crew that demonstrated our (pre-alpha) television studio in the cloud project. During the show Ryerson was invited to the IBC show held in Amsterdam last September. Since we thought we might have a stable version of our FFMPEG-based video compositing engine done by then (and who doesn't want to visit Amsterdam) IBC became a great deadline to work towards. As we got into the summer I realised I couldn't go and so we sent the two Computer Science students working on the project: Igor and Jimmy. Everything seemed to go well - with the exception of their cab colliding with a streetcar - until they got back and I heard the truth.

Whenever they did a demonstration, everything would work fine for a while. Multiple video streams coming into FMS would be sent over to the FFMPEG server where they would be composited into a single stream and be sent back to FMS. But at some point FMS would reject the stream with a "Clients not allowed to broadcast message" in the applications log. Jimmy and Igor didn't seem too concerned. I think they were proud of how they handled the demos - they don't think anyone noticed the problem. They decided one of them would work on fixing it and the other would work on getting FFMPEG working with GPU acceleration. I said no - they both had to work on the bug - because it is a show stopper. And, as it turns out, not just for us: http://forums.adobe.com/thread/722090?decorator=print&displayFullThread=true

So, what's the problem? The core log file tells you:

Bad network data; terminating connection : chunkstream error:message length 16723423 is longer than max rtmp packet length

It's a bug in FFMPEG's rtmp_write function in libavformat/rtmpproto.c and it only showed up when we switched to using h.264 instead of VP6 or Sorenson. The rtmp_write function is called repeatedly to send chunks of data to FMS. Whenever it is called it checks to make sure the data sent to it is at least 11 bytes in length:

 if (size < 11) {
   av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FLV packet too small %d\n", size);
   return 0;
}

The problem is that it doesn't differentiate between a buffer for a new packet and adding to an existing packet. That is it can't tell the difference between trying to create a packet from an 11 byte header and adding the last chunk of data to an existing packet, that just so happens to be 11 bytes in length or less. Finding and fixing the problem took a while but the fix is simple:

 if (size < 11 && !rt->flv_off) { // <--- Added "&& !rt->flv_off"
   av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FLV packet too small %d\n", size);
   return 0;
}

Now the function only returns if the buffer size is less than 11 and a packet does not already exist.

Now on to more interesting things, like GPU acceleration and the synchronization problem...


You might also be interested in:

News Topics

Recommended for You

Got a Question?