【问题标题】:How can I improve video quality of pjsip pjsua2 sample Android App?如何提高 pjsip pjsua2 示例 Android 应用程序的视频质量?
【发布时间】:2021-04-01 06:46:35
【问题描述】:

当前默认示例 Android pjsip pjsua2 示例应用发送的视频质量非常差,我希望将其改进为至少高清质量。我尝试使用以下方法,但它一直显示非常低的视频质量。如何提高传出视频质量?此示例应用能够从其他 sip 视频通话中接收高达 355 * 288 的视频质量,但它发送的视频质量非常差。

目前,我试图通过在拨打电话之前更新 MediaFormatvideo 文件中的以下值来实现高清视频。而且它根本无助于改善传出视频。我是否在错误的地方更新了这些属性?

目前它发送低于 192 * 144 的视频质量,不接受高于 352 * 288 的视频质量。如何更新它以支持至少 1280*720 的视频质量?

    MediaFormatVideo mf=new MediaFormatVideo();
    mf.setFpsNum(30);
    mf.setFpsDenum(1);
    mf.setAvgBps(512000);
    mf.setMaxBps(1024000);
    mf.setHeight(720);
    mf.setWidth(1280);

我正在更新这些设置如下:

   MyCall call = new MyCall(account, -1);
    CallOpParam prm = new CallOpParam(true);
    AccountVideoConfig avc=new AccountVideoConfig();
    MediaFormatVideo mf=new MediaFormatVideo();

    Log.e("javan-video",String.valueOf(avc.getAutoShowIncoming()));
    Log.e("javan-videofps",String.valueOf(mf.getFpsNum()));
    mf.setFpsNum(30);
    mf.setFpsDenum(1);
    mf.setAvgBps(512000);
    mf.setMaxBps(1024000);
    mf.setHeight(720);
    mf.setWidth(1280);
    Log.e("javan-videofps",String.valueOf(mf.getFpsNum()));


    try {
        call.makeCall("sip:"+dialno+"@peoplefone.ch", prm);
        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

       am.setSpeakerphoneOn(true);

         // startRinging();

    } catch (Exception e) {
        call.delete();
        return;
    }

    currentCall = call;
 showCallActivity();
}

我找到了文档,并以此为基础进行了实施,但我无法提高视频质量。

Framerate
Specify number of frames processed per second.

For encoding direction, configured via pjmedia_vid_codec_param.enc_fmt.det.vid.fps, e.g:
/* Sending @30fps */
param.enc_fmt.det.vid.fps.num   = 30;
param.enc_fmt.det.vid.fps.denum = 1;
Note:
that there is a possibility that the value will be adjusted to follow remote capability. For example, if remote signals that maximum framerate supported is 10fps and locally the encoding direction framerate is set to 30fps, then 10fps will be used.
limitation: if preview is enabled before call is established, capture device will opened using default framerate of the device, and subsequent calls that use that device will use this framerate regardless of the configured encoding framerate that is set above. Currently the only solution is to disable preview before establishing media and re-enable it once the video media is established.
For decoding direction, two steps are needed:
pjmedia_vid_codec_param.dec_fmt.det.vid.fps should be set to the highest value expected for incoming video framerate.
signalling to remote, configured via codec specific SDP format parameter (fmtp): pjmedia_vid_codec_param.dec_fmtp.
H263-1998, maximum framerate is specified per size/resolution basis, check ​here for more info.
/* 3000/(1.001*2) fps for CIF */
param.dec_fmtp.param[m].name = pj_str("CIF");
param.dec_fmtp.param[m].val = pj_str("2");
/* 3000/(1.001*1) fps for QCIF */
param.dec_fmtp.param[n].name = pj_str("QCIF");
param.dec_fmtp.param[n].val = pj_str("1");
H264, similar to size/resolution, the framerate is implicitly specified in H264 level (check the standard specification or ​this) and the H264 level is signalled via H264 SDP fmtp profile-level-id, e.g:
/* Can receive up to 1280×720 @30fps */
param.dec_fmtp.param[n].name = pj_str("profile-level-id");
param.dec_fmtp.param[n].val = pj_str("xxxx1f");
Bitrate
Specify bandwidth requirement for video payloads stream delivery.

This is configurable via pjmedia_vid_codec_param.enc_fmt.det.vid.avg_bps and pjmedia_vid_codec_param.enc_fmt.det.vid.max_bps, e.g:

/* Bitrate range preferred: 512-1024kbps */
param.enc_fmt.det.vid.avg_bps = 512000;
param.enc_fmt.det.vid.max_bps = 1024000;
Notes:

This setting is applicable for encoding and decoding direction, currently there is no way to set asymmetric bitrate. By decoding direction, actually it just means that this setting will be queried when generating bandwidth info for local SDP (see next point).
The bitrate setting of all codecs will be enumerated and the highest value will be signalled in bandwidth info in local SDP (see ticket #1244).
There is a possibility that the encoding bitrate will be adjusted to follow remote bitrate setting, i.e: read from SDP bandwidth info (b=TIAS line) in remote SDP. For example, if remote signals that maximum bitrate is 128kbps and locally the bitrate is set to 512kbps, then 128kbps will be used.
If codec specific bitrate setting signalling (via SDP fmtp) is desired, e.g: MaxBR for H263, application should put the SDP fmtp manually, for example:
/* H263 specific maximum bitrate 512kbps */
param.dec_fmtp.param[n].name = pj_str("MaxBR");
param.dec_fmtp.param[n].val = pj_str("5120"); /* = max_bps / 100 */

文档链接:enter link description here

 From: "0525512904" <sip:0525512904@95.128.80.93>;tag=1609930889511
I: To: <sip:90761330096@95.128.80.5>;tag=c6ce5331-3a35-44c8-bb80-23b6ec664085
I: CSeq: 1 INVITE
I: Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
I: Contact: <sip:90761330096@146.4.49.20:45483;transport=TLS;ob>
I: Supported: replaces, 100rel, timer, norefersub
I: Content-Type: application/sdp
I: Content-Length:   580
I: v=0
I: o=- 3818919690 3818919691 IN IP4 192.168.3.135
I: s=pjmedia
I: b=AS:352
I: t=0 0
I: a=X-nat:0
I: m=audio 4012 RTP/AVP 96 120
I: c=IN IP4 192.168.3.135
I: b=TIAS:64000
I: a=rtcp:4031 IN IP4 192.168.3.135
I: a=sendrecv
I: a=rtpmap:96 speex/16000
I: a=rtpmap:120 telephone-event/16000
I: a=fmtp:120 0-16
I: a=ssrc:1510027056 cname:365aaa4f448493db
I: m=video 4013 RTP/AVP 97
I: c=IN IP4 192.168.3.135
I: b=TIAS:256000
I: a=rtcp:4033 IN IP4 192.168.3.135
I: a=sendrecv
I: a=rtpmap:97 H264/90000
I: a=fmtp:97 profile-level-id=42e01e; packetization-mode=1
I: a=ssrc:1146236185 cname:365aaa4f448493db
I: a=rtcp-fb:* nack pli
I: --end msg--
E: ringing call

完整的日志链接sip call complete log

【问题讨论】:

  • 欢迎堆栈溢出。请在此处提供足够的信息,以便其他人通过在此处提供足够的信息来重现问题来帮助您
  • 我已经更新了我的问题。我可以在哪里以及如何更改 pjsip 中的视频分辨率 ...
  • @a_local_nobody 你能看看我更新的问题
  • 没有足够的信息来确定问题(如果有)。请记住,您正在指定您可以接收(而不是发送)的最大视频限制。然后,这仅限于对方可以收到的内容。如果对方不能显示超过 640x480,那么你的一方将限制自己只发送到那个。这由在 SDP 提议/答案中发送的 H264 配置文件级别 ID 确定。我建议您将 pjsip 日志级别设置为 4(从内存中)并查看它以查看它的内容。也许您需要研究 SDP 如何处理视频,以便您了解它在说什么。
  • 正如@ShanePowell 所说,查看 SDP 协商双方的 h264 配置文件级别。在这里查看更多信息:link

标签: java android pjsip pjsua2


【解决方案1】:

我仍然无法用给定的信息回答你的问题。

SDP 被用作SIP protocol 的负载类型。

您可以在此处的(部分)SIP 日志中看到:

Content-Type: application/sdp

SDP 是一个提议/应答协议。

鉴于您给出了 SIP INVITE 的不完整日志片段(我假设您没有给出整个 sip 消息),所以您只给出了 SDP 协议的 OFFER。 因此,您需要提供 OFFER 和 ANSWER 的完整图片。

此外,最好在视频编码器/解码器设置周围也包括其他 PJSIP 日志记录。

在你的报价中写着:

m=video 4013 RTP/AVP 97

表示可以发送/接收带有参数的视频:

a=rtpmap:97 H264/90000
a=fmtp:97 profile-level-id=42e01e; packetization-mode=1

这意味着可以发送/接收采样率为 90000(即 90kHz)的 H264。

H264参数设置为: a=fmtp:97 profile-level-id=42e01e;打包模式=1

所以...

profile-level-id=42e01e

https://www.rfc-editor.org/rfc/rfc6184

  profile-level-id:
     A base16 [7] (hexadecimal) representation of the following
     three bytes in the sequence parameter set NAL unit is specified
     in [1]: 1) profile_idc, 2) a byte herein referred to as
     profile-iop, composed of the values of constraint_set0_flag,
     constraint_set1_flag, constraint_set2_flag,
     constraint_set3_flag, constraint_set4_flag,
     constraint_set5_flag, and reserved_zero_2bits in bit-
     significance order, starting from the most-significant bit, and
     3) level_idc.  Note that reserved_zero_2bits is required to be
     equal to 0 in [1], but other values for it may be specified in
     the future by ITU-T or ISO/IEC.

profile_idc: 0x42 (66) 配置文件 iop:0xE0(二进制 11100000) level_idc: 0x1E (30)

https://en.wikipedia.org/wiki/Advanced_Video_Coding

profile_idc:66

基线资料 (BP, 66) 主要针对需要额外数据丢失鲁棒性的低成本应用程序,此配置文件用于某些视频会议和移动应用程序。此配置文件包括受约束的基线配置文件中支持的所有功能,以及可用于损失鲁棒性(或用于其他目的,例如低延迟多点视频流合成)的三个附加功能。自 2009 年约束基线配置文件定义以来,此配置文件的重要性已有所减弱。所有约束基线配置文件比特流也被视为基线配置文件比特流,因为这两个配置文件共享相同的配置文件标识符代码值。

profile-iop:二进制 11100000

这意味着:

constraint_set0_flag=1 (Constrained Baseline profile)
constraint_set1_flag=1
constraint_set2_flag=1

这两个值 IDC 和约束标志用于根据解码器可以支持的内容设置视频编码器。

级别:30 即 3.0

Level: 3.0 Maximum decoding speed (macroblocks/s): 40,500 Maximum
frame size (macroblocks): 1,620 Maximum video bit rate for video
coding layer (VCL): 10,000 Examples for high resolution @ highest
frame rate (maximum stored frames): 
  352×480@61.4 (12) 
  352×576@51.1 (10) 
  720×480@30.0 (6) 
  720×576@25.0 (5)

配置文件级别没有指定视频分辨率,是手动指定最大帧大小/比特率。可以“适合”这些限制的任何分辨率/帧率组合都是有效的。 这是将分辨率/帧率列表列为有效的地方。

因此 720×480 @ 30fps 或 720×576 @ 25fps 对于 3.0 级配置文件有效。

offer告诉对方的是:

  1. 本端只能DECODE Con​​strained Baseline Profile H264编码流。
  2. 这一面只能解码最高 3.0 级比特率(即上面的分辨率/fps 组合列表)

报价并未说明设备将向对方发送什么内容,这取决于您的本地设置以及对方所说的可以解码的内容。

PJSIP 将根据您的设置和支持的报价解码“选择”它可以发送的最佳分辨率/fps(这就是为什么您可以查看有关编码器设置的 PJSIP 日志)以了解它基于 SDP 发送的内容ANSWER(未提供)。

视频不必是对称的。 即根据相机/屏幕硬件,您可能会显示您可以发送的不同分辨率。

这也没有考虑在流式传输期间动态变化的分辨率(例如,纵向/横向翻转或基于 RTCP 报告中网络带宽变化的分辨率增加/减少)。 对此进行调查的唯一方法可能是捕获和解码 H264 流以了解它在做什么。 PJSIP 日志也可能会告诉您。

更新

查看 pjsip 日志输出,您可以在 INVITE 中看到 SDP 提议和 200 OK 中的答案。

I: 11:13:36.176           pjsua_core.c  .RX 1119 bytes Response msg 200/INVITE/cseq=22580 (rdata0x6f73203b18) from TLS 95.128.80.3:5061:
I: SIP/2.0 200 OK
I: To: <sip:0074444@james.com>;tag=61c5c92f
I: Via: SIP/2.0/TLS 146.4.49.20:49305;received=146.4.49.20;rport=49305;branch=z9hG4bKPjdad60ffa-6072-4c6d-8eb1-4a32ab26443a;alias
I: Record-Route: <sip:95.128.80.5;r2=on;lr=on;did=e8.cc62>,<sip:95.128.80.3:5061;transport=tls;r2=on;lr=on;did=e8.cc62>
I: CSeq: 22580 INVITE
I: Call-ID: 0e7676b2-1ca2-48b2-9696-f7e6dc7e1ec9
I: From: <sip:0677777@james.com>;tag=0b4094bb-b47e-4132-960c-ac564015efa0
I: Content-Type: application/sdp
I: Contact: <sip:peoplefone@95.128.80.93:5060;alias=95.128.80.93~5060~1>
I: Content-Length: 535
I: v=0
I: o=- 3819003211 3819003212 IN IP4 95.128.80.5
I: s=pjmedia
I: b=AS:352
I: t=0 0
I: a=X-nat:0
I: m=audio 20918 RTP/AVP 96 120
I: c=IN IP4 95.128.80.5
I: b=TIAS:64000
I: a=rtpmap:96 speex/16000
I: a=rtpmap:120 telephone-event/16000
I: a=fmtp:120 0-16
I: a=ssrc:1254727526 cname:496ca0741b8de59f
I: a=sendrecv
I: a=rtcp:20919
I: m=video 20956 RTP/AVP 97
I: c=IN IP4 95.128.80.5
I: b=TIAS:256000
I: a=rtpmap:97 H264/90000
I: a=fmtp:97 profile-level-id=42e01e; packetization-mode=1
I: a=ssrc:977888024 cname:496ca0741b8de59f
I: a=rtcp-fb:* nack pli
I: a=sendrecv
I: a=rtcp:20957
I: --end msg--

从答案中您可以看到它使用与报价相同的 H264 参数进行了回答:

I: m=video 20956 RTP/AVP 97
...
I: a=rtpmap:97 H264/90000
I: a=fmtp:97 profile-level-id=42e01e; packetization-mode=1

因此它将接受高达 H264 级别 3.0 的比特率。

如果您查看捕获设备(相机)的初始化,我们会看到以下日志:

I: 11:13:36.270             vid_port.c  .........Opening device OpenGL renderer [OpenGL] for render: format=I420, size=352x288 @15:1 fps

这意味着安卓前置摄像头已以 352x288 @ 15fps 的分辨率打开。

我认为这是您所说的视频质量问题的原因。

查看 pjsip 的源代码,它会枚举具有支持参数的相机。

然后,支持的捕获分辨率大小由根据可以发送的“允许”分辨率大小缩小的默认捕获分辨率大小确定。

由于允许的尺寸大于 352x288@15,所以我只能假设你的 Andriod 前置摄像头的默认捕获分辨率是 352x288@15。

您可以尝试使用后置摄像头而不是前置摄像头,看看您是否获得了 getter 解决方案或其他具有更好前置摄像头的 Andriod 设备。

PjSip 使用 android.hardware.Camera API 来访问和使用相机设备。 有关 pjsip 如何使用相机设备的详细信息,请参阅 PjCameraInfo 和 PjCamera。

【讨论】:

    【解决方案2】:

    您可能需要将 h264 编码 profile-level-id 更改为 3.1 级。它使 SDP 协商到 1280x720@30。

    为此,请将 h264 参数 profile-level-id 从 42e01e 更改为 42e01f(其中 1e == 30 和 1f == 31)

    我不知道函数是什么,但在 C++ 中 pjsua 是 setVideoCodecParam 和 getVideoCodecParam。

    可以在这个 wiki 中找到更多信息:https://trac.pjsip.org/repos/wiki/Video_Users_Guide#Sizeorresolution

    和 RFC:https://datatracker.ietf.org/doc/rfc6184/

    【讨论】:

      猜你喜欢
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多