[FFmpeg-devel] [PATCH] Add an RTSP muxer

Martin Storsjö martin
Sat Jan 9 20:12:22 CET 2010

On Sat, 9 Jan 2010, Luca Abeni wrote:

> I finally have some time for having a better look at your patches, and try
> them... I have no DSS installation, so I cannot test the RTSP muxer right now
> (I am installing a DSS in a virtual machine, so I hope to be able to test the
> muxer in a short time).

Thanks for taking the time to look at it!

IIRC, using this doesn't require too much config of the DSS - after 
getting it up and running, you should be able to send streams to it using 
this muxer, and then just connect to the same URL with a player.

> In the meanwhile, here are some untested comments on the code (I just quote
> the modified code, not the exact patch):
> 1) You do something like
> +                if (rt->is_output) {
> +                     AVFormatContext *rtpctx = rtsp_st->transport_priv;
> +                     /* Don't call av_write_trailer if av_write_header
> +                      * hasn't been called yet. Use ->priv_data to check
> +                      * for this. */
> +                     if (rtpctx->priv_data)
> +                         av_write_trailer(rtpctx);
> Maybe this "if" can be avoided? (what happens if we try to call
> av_write_trailer() anyway? I think it will just fail, no? Otherwise, can we
> ensure that transport_priv is not set if av_write_header has not been called?)

If av_write_trailer is called on an AVFormatContext that hasn't had 
av_write_header called yet, bad things may happen. In case of the RTP 
muxer, priv_data is null and rtp_write_trailer dereferences it. (The same 
applies for most other muxers, too, av_write_trailer mustn't be called if 
av_write_header hasn't been called.)

> 2) I think the "rtp_pb" field of RTSPStream is unneeded, right?

Yes, that's one of the patches that can be dropped if this approach is 

> 3) Instead of doing
> +            if (!av_new_stream(rtpctx, 0)) {
> +                err = AVERROR(ENOMEM);
> +                goto fail;
> +            }
> and
> +            /* Remove the local codec, link to the original codec
> +             * context instead, to give the rtp muxer access to
> +             * codec parameters. */
> +            av_free(rtpctx->streams[0]->codec);
> +            rtpctx->streams[0]->codec = st->codec;
> Cannot you simply do
> 	rtpctx->streams[0] = st;
> 	rtpctx->nb_streams = 1;

No, unfortunately not. There's a lot of internal logic within 
av_write_frame (or specifically, within compute_pkt_fields2) that update 
parameters within AVStream. The packet has been fed through this function 
once when passed from the user into rtsp_write_packet, and if using the 
exact same AVStream object, we'd try to write the same packet once again 
into the same AVStream, resulting in "non monotone timestamps" errors, 
among others.

Exactly this point would have been good to check how it's done with other 
chained muxers, had there been examples of such. :-)

> 4) In rtsp_write_packet(), fd_max looks useless

Probably yes, those parts are copied from rtsp_read_packet without too 
much thought.

> 5) In rtsp_write_packet(), before invoking av_write_frame() you call
> av_rescale_q() to convert the timebase. I think this can be avoided by setting
> the timebase of the RTSP's AVStream equal to the timebase of the RTP muxer's
> AVStream. Basically, after invoking av_write_header() for the RTP muxer you
> can properly set the timebase for the corresponding RTSP AVStream.

Hmm, that's a good idea, I'll have to test it.

Generally, is the amount of ugliness due to using chained muxers small 
enough for you to prefer this version over the initial one using an 
internal muxer interface?

> Also, I am wondering if the initialisation of the RTP Muxer's AVFormatContext
> can be done in rtsp_open_transport_ctx() (instead of initialising it earlier
> and only calling av_write_header() in rtsp_open_transport_ctx()). Basically,
> in this way the SDP would be created based on the RTSP AVFormatContext (as
> your initial patch did), and the RTP muxers would be initialised only later.
> I am not sure if this approach would simplify the code or not...

That would ease at least some things, yes. Then all the creation of the 
chained RTP muxers and their AVFormatContext could happen at the correct 
place, within rtsp_open_transport_ctx.

As you pointed out in some earlier comment, creating SDPs based on URLs 
starting with anything else than rtp:// should probably be disallowed, I 
thought the more correct approach would be to generate the SDP from the 
RTP muxers, instead of from the RTSP context and its AVStreams. But if 
you're OK with creating the SDP based on the RTSP context and URL, I think 
this can be a bit simplified.

That also implies that the hostname->IP conversion needed for the SDP 
either has to be in the SDP creator (as in my patch), or we need to set 
AVFormatContext->filename to some temporary URL containing numeric IPs 
while creating the SDP, and then later reverting to the correct one again.

Having the resolve within the SDP creator is a good safeguard IMO, but 
that patch should at least wait until the getaddrinfo/getnameinfo stuff 
from my other thread is applied, so that I can clean it up to use more 
flexible APIs.

// Martin

More information about the ffmpeg-devel mailing list