Lorenzo Miniero wrote:
Hi all,
apologies if this has been discussed before, but I couldn't find
anything in the recent months on this group so I thought I'd write anyway.
As a few others, I believe, I have been trying to find a way to make
codec modules more aware of what's happening on the wire. In particular,
the motivation for that comes from an attempt to make the open source
Opus codec module more responsive and adaptive to changes in the
network, taking advantage of the functionality the library provides in
that respect (e.g., dynamic bitrate adaptation). The best approach to do
that would obviously be providing codec modules with info on the RTCP
feedback loop, e.g., in terms of losses the recipient has experienced,
so that you can, for instance, change the bitrate in the encoder.
Unfortunately, as of now there doesn't seem to be any way to make this
possible, at least not in an easy way, in Asterisk out of the box.
I've been investigating a few ways to do that, and have come up with
some possible approaches, that I first wanted to discuss with you guys
though, first of all to make sure I'm actually on the right path, and
then to evaluate whether or not any of those can actually be integrated
within the Asterisk code base (as I do believe such a feedback loop
would be beneficial to other codec modules as well, and not only Opus).
If you're interested in some more motivation behind this, you can read
my discussion with Alexander Traud in a comment to his fork to the
asterisk-opus repo here: https://github.com/traud/asterisk-opus/issues/3
For the sake of completeness, Alexander himself thought of a possible
approach for integrating this feedback in a comment to another post:
https://github.com/seanbright/asterisk-opus/issues/25#issuecomment-249420010
where the idea is to pass a reference of the ast_rtp_instance into the
codec module itself. While this could possibly do the trick, I don't
believe this would be a viable option, as it would break the
architecture and module relationships, but I thought I'd mention it anyway.
One possible option that I had thought about was extending ast_frame to
convey RTCP feedback to modules, along with media to translate. This
would allow such feedback to take the same "path" as media packets,
meaning codec modules wouldn't need to be aware of any additional
core-related feature, but only that sometimes they might receive control
data instead of media to translate. Anyway, this could probably be
problematic to integrate with the translator's architecture, and would
probably need "cooperation" from channel modules as well, so may be a
bit overkill and bug-prone.
I don't think the ast_frame needs to be extended, but merely a new frame
type added that has a payload defined for this purpose. Right now
reading RTCP data returns a null frame. It can be changed to return this
new frame with the data. The ast_read function can recognize this frame
type and invoke what ever logic may be required. This can include giving
this data to the translation path (implementations can be changed to
explicitly define that they support it). This also does not alter the
threading model and gives a guarantee that the codec won't have to
protect itself, like would need to be done for a stasis message.
Another possible approach, and possibly the way to go, is to make use of
the Stasis message bus, something I was not aware of until I watched
Matt's excellent presentation at a conference recently. I saw how the
RTP engine in Asterisk does publish RTCP feecback on the bus, and that
you can subscribe to that as other events (as the HEP integration does,
for instance) from other parts of the code. I tried doing the same
within the Opus codec implementation, and apart from some quirks (e.g.,
weird fields in report blocks, like negative source_ssrc) it seemed to
do exactly what I was looking for. The only problem, though, is that
while a Stasis event contains a whole lot of info, codec modules are
pretty much clueless and have no way of matching a specific event
related to a specific call to a translator context they're handling. In
fact, AFAIK codec modules have no visibility at all of the channel a
translator is associated with, or of other identifiers it could rely on.
Thinking about this I did find a way to implement some kind of loose
mapping by extending the ast_frame structure with two new properties,
"ssrc" and "themssrc": basically, anytime an RTP packet is received, the
RTP engine copies the local and remote SSRC to the frame before passing
it to the core. When the first packet gets to the codec module, it can
keep track of them and save them locally to its own internal struct. So,
when a new event comes later from Stasis (e.g., an RTCP RR), it can look
at the SSRC it relates to and match it with the SSRCs it is aware of, so
that it knows it's related to a specific translator context and react
accordingly. While this seems effective, it has a few issues, though.
For instance, there's no way to assume remote SSRCs will be unique,
which means this could result in either missing or misleading feedback
in some cases, or even that they'll stay the same for the whole call.
Another aspect I haven't considered is the possible overhead, although I
don't think crawling a JSON object should take much resources. Besides,
I still haven't understood how Asterisk hashtables work, so this part is
still just theory :-)
Personally I'm not a huge fan of using the stasis messages for exactly
the reason you've given in your follow-up email. There's no obvious
reliable data to key off of and it also requires synchronization between
the thread handling the message and the thread doing the transcoding.
This changes the threading model for transcoding enough to be of a
concern to me and also introduces another lock.
That's basically it. Do you have any feeling/feedback on this? Is this
actually worth investigating, and do you believe I'm on the right track?
Any suggestion on how to make the mapping more effective in the codec
module? I'm of course willing to contribute to such an effort, if it's
deemed worthwhile.
Cheers,
--
Joshua Colp
Digium, Inc. | Senior Software Developer
445 Jan Davis Drive NW - Huntsville, AL 35806 - US
Check us out at: www.digium.com & www.asterisk.org
--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --
asterisk-dev mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-dev