Hi Hakan, True, that is the recommended behavior by the RFC, but in reality it may be impractical. For example, in the scenario mentioned in the RFC, always offering video upon receiving offerless re-INVITE will result in repeated video and media transport setup + teardown, which can add more delay, and thus inefficient and undesirable. Also, the note right below the part you quoted also says: " NOTE: The behavior above is recommended, but it is not always achievable, for example, in some interworking scenarios. Or, the offerer may simply not have enough resources to offer "everything" at that point. Even if the UAS is not able to offer any other SDP that the one currently being used, it should not reject the re- INVITE. Instead, it should generate an offer with the currently used SDP with "o=" line unchanged." So I still think that PJSIP's behavior is valid since it offers the currently used SDP. The only problem I see, after looking at your log and testing it myself, is that PJSIP's "o=" line is changed. This, we can fix, but as for the default behavior, IMO, it should remain as it is. And since PJSIP already offers a customization via the callback, which you have rightly used, it's quite straightforward to change this. Regards, Ming On Fri, Sep 28, 2018 at 10:14 PM, Håkan Berg <hakan.berg@xxxxxxxx> wrote: > Hi Ming, > I see what you mean and you're right, the SDP is strictly speaking not broken. > I see it as a legal SDP that does not reflect the users intention. > > I'm building my case mostly on the info in RFC6337, especially https://tools.ietf.org/html/rfc6337#section-5.2.5 since it highlights the problem with this SDP, at least the way I see it. > > The log entry you're referring to is the first INVITE in the sequence of events happening in the unhold scenario, and my understanding is that there's more to it than meets the eye. Yes, the remote offered video (and audio) inactive, but then directly afterwards it requests a new SDP in order to re-establish audio AND video. RFC6337 states among other things: > > "When the new offer is sent in response to an offerless (re-)INVITE, > it should be constructed according to the General Principle for > Constructing Offers and Answers (Section 5.1 ): all codecs the UA is > currently willing and able to use should be included, not just the > ones that were negotiated by previous offer/answer exchanges." > > > I'll summarize in simplified terms the chain of events in the log, to the best of my knowledge: > > 08:31:04.625 INVITE SDP pjsip->cisco (pjsip sends the initial invite, audio&video sendrecv) > 08:31:09.399 200 OK SDP pjsip <- cisco (cisco accepts pjsips call, audio&video sendrecv) > > 08:31:14.431 INVITE SDP pjsip <- cisco (user press hold on cisco, cisco sends new invite with audio&video inactive) > 08:31:14.569 OK SDP pjsip -> cisco (pjsip accepts the new SDP, call is on hold with audio&video inactive) > 08:31:14.575 INVITE pjsip <- cisco (cisco sends a late offer INVITE following the previous INVITE, as part of call hold) > 08:31:14.575 200 OK SDP pjsip -> cisco (pjsip sends an offer in the 200 OK reply, as mandated by rfc6337, offering audio&video sendrecv) > 08:31:14.588 ACK SDP pjsip <- cisco (cisco ACK the offered SDP but modifies it for hold music: audio sendonly, video inactive. Call is still on hold) > > 08:31:19.240 INVITE SDP pjsip <- cisco (user pressed unhold, cisco wants to stop the hold music, audio&video inactive) > 08:31:19.240 200 OK SDP pjsip -> cisco (pjsip accepts the new SDP, hold music stops) > 08:31:19.248 INVITE pjsip <- cisco (cisco sends a late offer INVITE following the previous INVITE, as part of call unhold) > 08:31:19.248 200 OK SDP pjsip -> cisco (pjsip sends an offer in the 200 OK reply, as mandated by rfc6337, offering audio sendrecv but video inactive. This is the problem imo, see rfc6337 5.2.5) > 08:31:19.256 ACK SDP pjsip <- cisco (cisco ACK the offered SDP, call is unheld but video is naturally not re-established: audio sendrecv, video inactive) > > > You mentioned that " As for the disabled video, it's because in the previous offer, remote requested it". I'm don't think the remote requested it in terms of it's final intention. It was one event in a chain of events from the remote, with the last one being that the remote requested pjsip to send its capabilities (i.e. late offer), but because of the supposed bug, pjsip will not offer video despite being video capable (unless the developer registers a callback which really shouldn't be a requirement in my opinion. Especially since it's not documented as such). > > > Thank you for your ongoing effort in this! > > Br, > /Håkan > > > -----Original Message----- > From: pjsip [mailto:pjsip-bounces@xxxxxxxxxxxxxxx] On Behalf Of Ming > Sent: den 28 september 2018 03:35 > To: pjsip list <pjsip@xxxxxxxxxxxxxxx> > Subject: Re: Bug report: pjsua has no video on call unhold on cisco pbx > > Hi Hakan, > > The SDP is actually perfectly fine. > > https://tools.ietf.org/html/rfc4566#section-6 > Although an RTP profile may make static assignments of payload > type numbers to payload formats, it is more common for that > assignment to be done dynamically using "a=rtpmap:" attributes. > As an example of a static payload type, consider u-law PCM > coded single-channel audio sampled at 8 kHz. This is > completely defined in the RTP Audio/Video profile as payload > type 0, so there is no need for an "a=rtpmap:" attribute > > 31 is a static payload type, which corresponds to H261 > > An example can be found here: > https://www.rfc-editor.org/rfc/rfc3264.txt > search for (m=video 0) > > As for the disabled video, it's because in the previous offer, remote requested it and it has been accepted (below is the summarized > message): > 08:31:19.240 pjsua_core.c .RX 1299 bytes Request msg > INVITE/cseq=103 (rdata0x7f1f5c0008e8) from UDP 10.0.0.1:5060: > INVITE sip:7004@10.0.0.5:5060;ob SIP/2.0 > CSeq: 103 INVITE > m=video 0 RTP/AVP 126 > a=inactive > > Best regards, > Ming > > > On Thu, Sep 27, 2018 at 1:48 PM, Håkan Berg <hakan.berg@xxxxxxxx> wrote: >> Hi Ming, >> >> I agree that the recipient is free to provide an offer, but in this case it does not make sense for pjsip to provide an offer with a broken sdp in it, and the pjsua app should not have to register a callback to fix that. >> >> Looking at the problematic last offer sent from pjsip, it has a line >> like >> (m): video 0 RTP/AVP 31 >> but no correseponding rtpmap, and most previous offers from pjsip in that session does have correct and working SDPs with a resulting good video received by the remote. >> >> Why would pjsip offer an SDP that effectively renders video inactive? I would argue that’s done because of the bug, namely apply_call_setting() not being called, and bogus default data happens to be placed in the SDP. >> >> >> >> From the log, the problematic offer from pjsip when remote wants to unhold: >> >> 08:31:19.248 pjsua_call.c ......Call 0: asked to send a new offer >> 08:31:19.248 inv0x20161f8 ......Sending Response msg 200/INVITE/cseq=104 (tdta0x7f1f5c93c468) >> 08:31:19.248 dlg0x20161f8 .......Sending Response msg 200/INVITE/cseq=104 (tdta0x7f1f5c93c468) >> 08:31:19.248 tsx0x7f1f5c002cc8 .......Sending Response msg 200/INVITE/cseq=104 (tdta0x7f1f5c93c468) >> in state Trying >> 08:31:19.248 sip_resolve.c ........Target '10.0.0.1:5060' type=UDP resolved to '10.0.0.1:5060' >> type=UDP (UDP transport) >> 08:31:19.248 pjsua_core.c ........TX 1172 bytes Response msg 200/INVITE/cseq=104 (tdta0x7f1f5c >> 93c468) to UDP 10.0.0.1:5060: >> SIP/2.0 200 OK >> Via: SIP/2.0/UDP >> 10.0.0.1:5060;received=10.0.0.1;branch=z9hG4bKac752b67ba38 >> Call-ID: 62523409-8a14-469c-8352-3832a7de0701 >> From: >> <sip:1012@10.0.0.1>;tag=207142~4be90327-72fd-4c7c-9d1d-8e146fc96532-20 >> 849481 >> To: <sip:7004@10.0.0.1>;tag=b31381ed-00e1-4dc3-82f8-3f4368805895 >> CSeq: 104 INVITE >> Session-Expires: 1800;refresher=uac >> Require: timer >> Contact: <sip:7004@10.0.0.5:5060;ob> >> Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, >> NOTIFY, REFER, MESSAGE, OPTIONS >> Supported: replaces, 100rel, timer, norefersub >> Content-Type: application/sdp >> Content-Length: 550 >> >> v=0 >> o=- 3746845864 3746845868 IN IP4 10.0.0.5 s=pjmedia >> b=AS:84 >> t=0 0 >> a=X-nat:0 >> m=audio 4000 RTP/AVP 98 97 99 104 3 0 8 9 96 c=IN IP4 10.0.0.5 >> b=TIAS:64000 >> a=rtcp:4001 IN IP4 10.0.0.5 >> a=sendrecv >> a=rtpmap:98 speex/16000 >> a=rtpmap:97 speex/8000 >> a=rtpmap:99 speex/32000 >> a=rtpmap:104 iLBC/8000 >> a=fmtp:104 mode=30 >> a=rtpmap:3 GSM/8000 >> a=rtpmap:0 PCMU/8000 >> a=rtpmap:8 PCMA/8000 >> a=rtpmap:9 G722/8000 >> a=rtpmap:96 telephone-event/8000 >> a=fmtp:96 0-16 >> a=ssrc:219786230 cname:54ddf01b2db5c07e m=video 0 RTP/AVP 31 c=IN IP4 >> 127.0.0.1 >> >> --end msg-- >> >> >> >> >> From the log, an earlier request for pjsip to send a new offer, working as intended: >> >> 08:31:14.575 pjsua_call.c ......Call 0: asked to send a new offer >> 08:31:14.575 inv0x20161f8 ......Sending Response msg 200/INVITE/cseq=102 (tdta0x7f1f5c93f6a8) >> 08:31:14.575 dlg0x20161f8 .......Sending Response msg 200/INVITE/cseq=102 (tdta0x7f1f5c93f6a8) >> 08:31:14.575 tsx0x7f1f5c002cc8 .......Sending Response msg 200/INVITE/cseq=102 (tdta0x7f1f5c93f6a8) >> in state Trying >> 08:31:14.575 sip_resolve.c ........Target '10.0.0.1:5060' type=UDP resolved to '10.0.0.1:5060' >> type=UDP (UDP transport) >> 08:31:14.575 pjsua_core.c ........TX 1358 bytes Response msg 200/INVITE/cseq=102 (tdta0x7f1f5c >> 93f6a8) to UDP 10.0.0.1:5060: >> SIP/2.0 200 OK >> Via: SIP/2.0/UDP >> 10.0.0.1:5060;received=10.0.0.1;branch=z9hG4bKac713bbfb438 >> Call-ID: 62523409-8a14-469c-8352-3832a7de0701 >> From: >> <sip:1012@10.0.0.1>;tag=207142~4be90327-72fd-4c7c-9d1d-8e146fc96532-20 >> 849481 >> To: <sip:7004@10.0.0.1>;tag=b31381ed-00e1-4dc3-82f8-3f4368805895 >> CSeq: 102 INVITE >> Session-Expires: 1800;refresher=uac >> Require: timer >> Contact: <sip:7004@10.0.0.5:5060;ob> >> Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, >> NOTIFY, REFER, MESSAGE, OPTIONS >> Supported: replaces, 100rel, timer, norefersub >> Content-Type: application/sdp >> Content-Length: 736 >> >> v=0 >> o=- 3746845864 3746845866 IN IP4 10.0.0.5 s=pjmedia >> b=AS:352 >> t=0 0 >> a=X-nat:0 >> m=audio 4000 RTP/AVP 98 97 99 104 3 0 8 9 96 c=IN IP4 10.0.0.5 >> b=TIAS:64000 >> a=rtcp:4001 IN IP4 10.0.0.5 >> a=sendrecv >> a=rtpmap:98 speex/16000 >> a=rtpmap:97 speex/8000 >> a=rtpmap:99 speex/32000 >> a=rtpmap:104 iLBC/8000 >> a=fmtp:104 mode=30 >> a=rtpmap:3 GSM/8000 >> a=rtpmap:0 PCMU/8000 >> a=rtpmap:8 PCMA/8000 >> a=rtpmap:9 G722/8000 >> a=rtpmap:96 telephone-event/8000 >> a=fmtp:96 0-16 >> a=ssrc:219786230 cname:54ddf01b2db5c07e m=video 4002 RTP/AVP 97 c=IN >> IP4 10.0.0.5 >> b=TIAS:256000 >> a=rtcp:4003 IN IP4 10.0.0.5 >> a=sendrecv >> a=rtpmap:97 H264/90000 >> a=fmtp:97 profile-level-id=42e01e; packetization-mode=1 >> a=ssrc:1687763237 cname:54ddf01b2db5c07e >> >> --end msg-- >> >> >> >> Let me know if you need gdb logs demonstrating the issue. >> >> Thank you for looking into this. >> Br, >> /Håkan >> >> -----Original Message----- >> From: pjsip [mailto:pjsip-bounces@xxxxxxxxxxxxxxx] On Behalf Of Ming >> Sent: den 27 september 2018 06:20 >> To: pjsip list <pjsip@xxxxxxxxxxxxxxx> >> Subject: Re: Bug report: pjsua has no video on call unhold on >> cisco pbx >> >> Hi Hakan, >> >> I'm not sure if it's a bug. As far as I remember (perhaps you need to search the RFC for this), sending INVITE without SDP doesn't constitute an unhold request, and the recipient is then free to provide an offer, which in this case, means that PJSIP will offer the state of the currently active session. >> >> If you want to change this behavior, your workaround is actually already the solution, which is correctly implemented in the application (pjsua_app is actually a sample app) and doesn't require any modification within the library. >> >> Regards, >> Ming >> >> On Wed, Sep 26, 2018 at 12:27 AM Håkan Berg <hakan.berg@xxxxxxxx> wrote: >>> >>> Hi Ming, >>> >>> Yes, you're correct. The remote is sending a re-INVITE without SDP when doing unhold. >>> >>> Attaching log file. >>> >>> Br, >>> /Håkan >>> >>> -----Original Message----- >>> From: pjsip [mailto:pjsip-bounces@xxxxxxxxxxxxxxx] On Behalf Of Ming >>> Sent: den 25 september 2018 03:04 >>> To: pjsip list <pjsip@xxxxxxxxxxxxxxx> >>> Subject: Re: Bug report: pjsua has no video on call unhold on >>> cisco pbx >>> >>> Hi Hakan, >>> >>> Since I can't access the Cisco server from here, can you forward us the log (level 5, as text attachment)? >>> >>> Based on your description, since app needs to overwrite callback on_call_tx_offer(), does it mean that the remote is sending re-INVITE without SDP when trying to unhold? >>> >>> Regards, >>> Ming >>> On Mon, Sep 24, 2018 at 9:03 PM Håkan Berg <hakan.berg@xxxxxxxx> wrote: >>> > >>> > Hi, >>> > I believe I've found a problem in pjsua: When registered to a cisco unified call manager pbx (10.5 in my case) and calling to a video phone endpoint on that pbx, the video negotiation in pjsip fails if the endpoint phone puts pjsip on hold and then unhold again. >>> > The SDP sent from pjsip seems to be missing vital video lines: >>> > m=video 0 RTP/AVP 31 >>> > c=IN IP4 127.0.0.1 >>> > a=sendrecv >>> > >>> > Whereas a working video SDP might include something like this: >>> > m=video 4006 RTP/AVP 97 >>> > c=IN IP4 10.0.0.5 >>> > b=TIAS:768000 >>> > a=rtcp:4007 IN IP4 10.0.0.5 >>> > a=sendrecv >>> > a=rtpmap:97 H264/90000 >>> > a=fmtp:97 profile-level-id=42000d >>> > >>> > I can reproduce it with pjsua-bin like so: >>> > >>> > git clone https://github.com/cisco/openh264.git >>> > cd openh264 >>> > make >>> > sudo make install >>> > cd .. >>> > wget http://pjsip.org/release/2.8/pjproject-2.8.tar.bz2 >>> > tar xvfj pjproject-2.8.tar.bz2 >>> > cd pjproject-2.8 >>> > ./configure >>> > echo "#define PJMEDIA_HAS_VIDEO 1" >> >>> > pjlib/include/pj/config_site.h make dep && make cd pjsip-apps/bin >>> > ./pjsua-x86_64-unknown-linux-gnu >>> > --playback-dev=1 --capture-dev=1 --id sip:1@10.0.0.1 --registrar >>> > sip:10.0.0.1 --realm "*" --username 1 --password hunter2 >>> > --app-log-level=3 --video >>> > >>> > press m, enter sip:2@10.0.0.1 >>> > Cisco phone on extension 2 rings, answer and press hold. Video goes to inactive, press hold button again to unhold call, video ends up still being inactive because of SDP negotiation problem. >>> > I can work around the problem by registering a callback function, but that should not be needed in my opinion: >>> > >>> > diff --git a/pjsip-apps/src/pjsua/pjsua_app.c.bak >>> > b/pjsip-apps/src/pjsua/pjsua_app.c >>> > index 51c4537..db6066a 100644 >>> > --- a/pjsip-apps/src/pjsua/pjsua_app.c.bak >>> > +++ b/pjsip-apps/src/pjsua/pjsua_app.c >>> > @@ -1226,6 +1226,12 @@ int stdout_refresh_proc(void *arg) >>> > return 0; >>> > } >>> > >>> > +static void >>> > +ON_CALL_TX_OFFER_WORKAROUND(pjsua_call_id call_id, void *reserved, >>> > + pjsua_call_setting *opt) { } >>> > + >>> > static pj_status_t app_init() >>> > { >>> > pjsua_transport_id transport_id = -1; @@ -1275,6 +1281,9 @@ >>> > static pj_status_t app_init() >>> > app_config.cfg.cb.on_nat_detect = &on_nat_detect; >>> > app_config.cfg.cb.on_mwi_info = &on_mwi_info; >>> > app_config.cfg.cb.on_transport_state = &on_transport_state; >>> > + >>> > + app_config.cfg.cb.on_call_tx_offer = >>> > + &ON_CALL_TX_OFFER_WORKAROUND; >>> > + >>> > app_config.cfg.cb.on_ice_transport_error = &on_ice_transport_error; >>> > app_config.cfg.cb.on_snd_dev_operation = &on_snd_dev_operation; >>> > app_config.cfg.cb.on_call_media_event = &on_call_media_event; >>> > >>> > >>> > >>> > This seems to be a problem because of the late offer mechanism that cisco uses, and pjsua-lib only "re-initialize media before creating SDP" if there's a on_call_tx_offer callback set (or call->med_prov_cnt is 0), see pjsua_call_on_create_offer(). >>> > This limitation does not seem to exist for things like pjsua_call_set_hold2(). But that's why the workaround gives a successful SDP negotiation: apply_call_setting() gets called. >>> > Let me know if you need any pcap dumps demonstrating the problem. >>> > >>> > Please advise. >>> > Br, >>> > /Håkan >>> > >>> > _______________________________________________ >>> > Visit our blog: http://blog.pjsip.org >>> > >>> > pjsip mailing list >>> > pjsip@xxxxxxxxxxxxxxx >>> > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >>> >>> _______________________________________________ >>> Visit our blog: http://blog.pjsip.org >>> >>> pjsip mailing list >>> pjsip@xxxxxxxxxxxxxxx >>> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >>> _______________________________________________ >>> Visit our blog: http://blog.pjsip.org >>> >>> pjsip mailing list >>> pjsip@xxxxxxxxxxxxxxx >>> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >> >> _______________________________________________ >> Visit our blog: http://blog.pjsip.org >> >> pjsip mailing list >> pjsip@xxxxxxxxxxxxxxx >> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >> _______________________________________________ >> Visit our blog: http://blog.pjsip.org >> >> pjsip mailing list >> pjsip@xxxxxxxxxxxxxxx >> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@xxxxxxxxxxxxxxx > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@xxxxxxxxxxxxxxx > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org _______________________________________________ Visit our blog: http://blog.pjsip.org pjsip mailing list pjsip@xxxxxxxxxxxxxxx http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org