On 16 September 2013 10:00, Martin Storsjö <[email protected]> wrote:
> On Mon, 16 Sep 2013, Josh Allmann wrote:
>
>> Sending audio/video on the same channel leads to non-montonic
>> timestamps when switching streams, so the RTMP timestamp delta
>> is incorrectly written as a large unsigned number.
>
>
> Can you elaborate this a little further, I'm not sure I totally understand
> what you mean is happening.
>

RTMP packet timestamps are transmitted as a delta from the absolute
timestamp of the previous packet in the same channel, and since
audio/video streams aren't guaranteed to be monotonic relative to one
another, we could have the following situation, with absolute
timestamps:

Video packet 1: Abs. timestamp 9
Audio packet 2: Abs. timestamp 10

uint32_t delta = 9 - 10 == 4294967295

>
>> ---
>> libavformat/rtmpproto.c |    5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
>> index 48eed56..74ca3d8 100644
>> --- a/libavformat/rtmpproto.c
>> +++ b/libavformat/rtmpproto.c
>> @@ -2599,6 +2599,7 @@ static int rtmp_write(URLContext *s, const uint8_t
>> *buf, int size)
>>         if (rt->flv_header_bytes < 11) {
>>             const uint8_t *header = rt->flv_header;
>>             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
>> +            int channel = RTMP_SOURCE_CHANNEL;
>>             bytestream_get_buffer(&buf_temp, rt->flv_header +
>> rt->flv_header_bytes, copy);
>>             rt->flv_header_bytes += copy;
>>             size_temp            -= copy;
>> @@ -2620,8 +2621,10 @@ static int rtmp_write(URLContext *s, const uint8_t
>> *buf, int size)
>>                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
>
>
> Shouldn't this be updated to use the new channel id as well?
>

Probably.

>
>>             }
>>
>> +            if (pkttype == RTMP_PT_VIDEO)
>> +                channel = RTMP_VIDEO_CHANNEL;
>>             //this can be a big packet, it's better to send it right here
>> -            if ((ret = ff_rtmp_packet_create(&rt->out_pkt,
>> RTMP_SOURCE_CHANNEL,
>> +            if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
>>                                              pkttype, ts, pktsize)) < 0)
>>                 return ret;
>>
>> --
>> 1.7.9.5
>
>
> How does this relate to the fact that the source channel is signalled in the
> gen_publish call as well? (Does it matter in any way, or is it just a
> coincidence that the publish method is sent on the same channel?)
>

Good catch, I thought it was a coincidence too, until I double-checked
the behavior of Flash player -- publish/play/closeStream are sent on
channel 8 if it's the first stream of the connection (which it usually
is), but video itself is sent on channel 6, which indicates 8 is some
sort of control channel for the stream.

Other implementations like the crtmpserver client use the regular
channel for invokes (3) without any ill effects, while librtmp uses 4
for publish (which is the audio channel), and 8 for play.

So it's all very inconsistent (and I suspect it doesn't matter much as
long as it's sent before any media), but I'll modify the behavior to
match that of Flash.

> Using RTMP_SOURCE_CHANNEL for one stream and RTMP_VIDEO_CHANNEL does feel a
> little assymetric to me, would it make more sense to always use both
> RTMP_{AUDIO,VIDEO}_CHANNEL and drop RTMP_SOURCE_CHANNEL, or add another
> source channel enum?
>

Addressed in the second patch, but given the changes needed above, I
might squash these two into one patch.

> // Martin
> _______________________________________________
> libav-devel mailing list
> [email protected]
> https://lists.libav.org/mailman/listinfo/libav-devel
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to