WebRTC オーディオおよびビデオ通話 - WebRTC ローカル ライブ高解像度で画面が表示されない問題

iOS 開発 - WebRTC ローカル ライブ高解像度で画面が表示されない問題

以前、WebRTC と ossrs を組み合わせてストリームをプッシュした場合、ossrs のプレーヤーは高解像度画像の問題を認識できませんでした。この質問に従って、解決策が見つかりました。

1.WebRTCとは

WebRTCとは何ですか?

WebRTC (Web Real-Time Communications) は、ネットワーク アプリケーションまたはサイトが仲介者なしでブラウザ間でピアツーピア (ピアツーピア) 接続を確立し、ビデオ ストリーミングや送信を実現できるリアルタイム通信テクノロジです。オーディオ ストリームまたはその他の任意のデータ。

2.ossrsとは何ですか?

オッサーとは何ですか
SRS (Simple Realtime Server) は、RTMP、WebRTC、HLS、HTTP-FLV、SRT などの複数のリアルタイム ストリーミング メディア プロトコルをサポートする、シンプルで効率的なリアルタイム ビデオ サーバーです。

公式サイトアドレス:https://ossrs.net/lts/zh-cn/

ここではiOS Google WebRTCとRTCライブブロードキャストを実現するossrsについては書きません。とりあえず、高解像度のローカルWebRTCライブブロードキャストで映像が表示されない問題を記録しておいて損はない。

3. 高解像度で画面が表示されない問題の解決策

ローカル WebRTC ライブの高解像度ライブ ブロードキャストで画像が表示されない問題は、SDP の profile-level-id に関連しています。

profile-level-id は、SPS の 2 番目から 4 バイトの Base16 エンコーディングです。これら 3 バイトの具体的な意味は次のとおりです。

sps[1] AVCProfileIndication
sps[2] profile_compatibility
sps[3] AVCLevlIndication

http://ja.wikipedia.org/wiki/H.264/MPEG-4_AVC#Levels
を実際に設定する場合、レベル値は 10 倍され、たとえばレベル 1.0 の場合、設定値は 0x0A になります。レベル3.0の場合、設定値は0x1Eです。例外はレベル 1b、設定値は 0x09

画像ソース ネットワーク (アドレスを忘れてしまいました、ブログ画像を引用する場合はメッセージを残してください)
ここに画像の説明を挿入

3番目はレベルを表しており、例えば1fの値は31、図から3.1、解像度は720 480 720 576 1280*720であることがわかります。

高解像度 1920 1080 2560 1920 3840*2160 が必要な場合は、レベル 5.1 の 16 進値を 33 に設定する必要があります。ここで設定された値は 42e033 です。

以下は SDP の例です

「コード」: 0、
「サーバー」: 「vid-415v5lz」、
“sdp”: “v=0\r\no=SRS/4.0.268(Leo) 94003279212192 2 IN IP4 0.0.0.0\r\ns=SRSPublishSession\r\nt=0 0\r\na=ice-lite\ r\na=グループ:バンドル 0 1\r\na=msid-semantic: WMS ライブ/ライブストリーム\r\nm=オーディオ 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 0.0.0.0\r\ na=ice-ufrag:q01184s8\r\na=ice-pwd:o25158210twbb093o342910094v0wo5k\r\na=フィンガープリント:sha-256 6A:66:81:7C:68:91:79:18:05:2C:EE:5F :BF:1B:4B:F4:78:C4:01:06:CC:CC:9E:F0:32:5B:72:21:4A:C2:A1:AA\r\na=セットアップ:パッシブ\r \na=mid:0\r\na=recvonly\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime =10;useinbandfec=1\r\na=候補:0 1 udp 2130706431 10.0.80.128 8000 typ ホスト世代 0\r\na=candidate:1 1 udp 2130706431 112.124.157.141 8000 typ ホスト世代 0\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 127\r\nc=IN IP4 0.0.0.0\r\na=ice-ufrag:q01184s8\r\na=ice-pwd:o25158210twbb093o342910094v0wo5k\r\na=フィンガープリント:sha-256 6A:66:81:7C:68:91:79:18:05:2C:EE:5F:BF:1B:4B:F4:78:C4:01:06:CC:CC:9E:F0 :32:5B:72:21:4A:C2:A1:AA\r\na=setup:passive\r\na=mid:1\r\na=extmap:5 http://www.ietf.org/ id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 H264/90000 \r\na=rtcp-fb:96 トランスポート-cc\r\na=rtcp-fb:96 ナック\r\na=rtcp-fb:96 ナックプリ\r\na=fmtp:96 レベル非対称許可= 1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:127 red/90000\r\na=candidate:0 1 udp 2130706431 10.0.80.128 8000 typ ホスト世代 0\r\na=候補:1 1 udp 2130706431 112.124.157.141 8000 typ ホスト世代 0\r\n”、org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 H264 /90000\r\na=rtcp-fb:96 トランスポート-cc\r\na=rtcp-fb:96 ナック\r\na=rtcp-fb:96 ナックプリ\r\na=fmtp:96 レベル-非対称- allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:127 red/90000\r\na=candidate:0 1 udp 2130706431 10.0.80.128 8000 typ ホスト世代 0\r\ na=候補:1 1 udp 2130706431 112.124.157.141 8000 typ ホスト世代 0\r\n”,org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 H264 /90000\r\na=rtcp-fb:96 トランスポート-cc\r\na=rtcp-fb:96 ナック\r\na=rtcp-fb:96 ナックプリ\r\na=fmtp:96 レベル-非対称- allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:127 red/90000\r\na=candidate:0 1 udp 2130706431 10.0.80.128 8000 typ ホスト世代 0\r\ na=候補:1 1 udp 2130706431 112.124.157.141 8000 typ ホスト世代 0\r\n”,141 8000 typ ホスト世代 0\r\n”、141 8000 typ ホスト世代 0\r\n”、
“セッションID”: “q01184s8:oPvh”
}

ここで profile-level-id=42e01f を確認できます。

WebRTC でローカル SDP の profile-level-id を 42e033 に置き換える場合

[weakSelf.webRTCClient offer:^(RTCSessionDescription *sdp) {
    
    
        DebugLog(@"changeSDP2Server offer sdp:%@", sdp);
        NSString *offerSDPString = [SDWebRTCSDPUtil setMediaBitrate:sdp.sdp media:@"video" bitrate:(6*1024*1024)];
        DebugLog(@"changeSDP2Server offerSDPString:%@", offerSDPString);
        [weakSelf changeSDP2Server:offerSDPString];
    }];

呼び出す前に、rtc/v1/publish/ インターフェイスを呼び出して取得したremoteSDPString の profile-level-id を 42e033 に変更します。

- (void)setRemoteDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
           completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;

テスト後、高解像度画像の切り替えは正常に表示できました。

NSString *resultRemoteSDPString = [SDWebRTCSDPUtil setMediaBitrate:remoteSDPString media:@"video" bitrate:(6*1024*1024)];
               DebugLog(@"changeSDP2Server resultRemoteSDPString:%@", resultRemoteSDPString);

               RTCSessionDescription *remoteSDP = [[RTCSessionDescription alloc] initWithType:RTCSdpTypeAnswer sdp:resultRemoteSDPString];
               [weakSelf.webRTCClient setRemoteSdp:remoteSDP completion:^(NSError * error) {
    
    
                   DebugLog(@"changeSDP2Server setRemoteDescription error:%@", error);
               }];

4. RTCVideoEncoderFactoryを通じて高解像度で画面が表示されない問題を解決

SDP の profile-level-id を変更することが最終的な解決策ではないので、最終的には RTCVideoEncoder の RTCVideoCodecInfo の constrainedHighParams の profile-level-id 値を使用して 42e033 を指定します

コーデックの constrainedHighInfo 要素と constrainedBaselineInfo 要素を設定します。

NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
    
    
    @"profile-level-id" : kLevelHighConstrainedHigh,
    @"level-asymmetry-allowed" : @"1",
    @"packetization-mode" : @"1",
  };
  RTCVideoCodecInfo *constrainedHighInfo =
      [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters:constrainedHighParams];
  [codecs addObject:constrainedHighInfo];

  NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
    
    
    @"profile-level-id" : kLevelHighConstrainedBaseline,
    @"level-asymmetry-allowed" : @"1",
    @"packetization-mode" : @"1",
  };
  RTCVideoCodecInfo *constrainedBaselineInfo =
      [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters:constrainedBaselineParams];
  [codecs addObject:constrainedBaselineInfo];

完全なコードは次のとおりです

SDRTCVideoEncoderFactory.h

#import <Foundation/Foundation.h>
#import <WebRTC/WebRTC.h>

/**
 + (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
   NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
     @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh,
     @"level-asymmetry-allowed" : @"1",
     @"packetization-mode" : @"1",
   };
   RTCVideoCodecInfo *constrainedHighInfo =
       [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name
                                    parameters:constrainedHighParams];
   NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
     @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline,
     @"level-asymmetry-allowed" : @"1",
     @"packetization-mode" : @"1",
   };
   RTCVideoCodecInfo *constrainedBaselineInfo =
       [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name
                                    parameters:constrainedBaselineParams];
   RTCVideoCodecInfo *vp8Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp8Name];
 #if defined(RTC_ENABLE_VP9)
   RTCVideoCodecInfo *vp9Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp9Name];
 #endif
   return @[
     constrainedHighInfo,
     constrainedBaselineInfo,
     vp8Info,
 #if defined(RTC_ENABLE_VP9)
     vp9Info,
 #endif
   ];
 }
 */

@interface SDRTCVideoEncoderFactory : NSObject<RTCVideoEncoderFactory>

@end

SDRTCVideoEncoderFactory.m

#import "SDRTCVideoEncoderFactory.h"

static NSString *kLevelHighConstrainedHigh = @"640c33";
static NSString *kLevelHighConstrainedBaseline = @"42e033";

@implementation SDRTCVideoEncoderFactory

- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info {
    
    
  if ([info.name isEqualToString:kRTCVideoCodecH264Name]) {
    
    
    return [[RTCVideoEncoderH264 alloc] initWithCodecInfo:info];
  } else if ([info.name isEqualToString:kRTCVideoCodecVp8Name]) {
    
    
    return [RTCVideoEncoderVP8 vp8Encoder];
  } else if ([info.name isEqualToString:kRTCVideoCodecVp9Name]) {
    
    
    return [RTCVideoEncoderVP9 vp9Encoder];
  }

  return nil;
}

- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
    
    
  NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array];

  NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
    
    
    @"profile-level-id" : kLevelHighConstrainedHigh,
    @"level-asymmetry-allowed" : @"1",
    @"packetization-mode" : @"1",
  };
  RTCVideoCodecInfo *constrainedHighInfo =
      [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters:constrainedHighParams];
  [codecs addObject:constrainedHighInfo];

  NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
    
    
    @"profile-level-id" : kLevelHighConstrainedBaseline,
    @"level-asymmetry-allowed" : @"1",
    @"packetization-mode" : @"1",
  };
  RTCVideoCodecInfo *constrainedBaselineInfo =
      [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecH264Name parameters:constrainedBaselineParams];
  [codecs addObject:constrainedBaselineInfo];

  RTCVideoCodecInfo *vp8Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp8Name parameters:nil];
  [codecs addObject:vp8Info];

#if defined(RTC_ENABLE_VP9)
    RTCVideoCodecInfo *vp9Info = [[RTCVideoCodecInfo alloc] initWithName:kRTCVideoCodecVp9Name];
    [codecs addObject:vp9Info];
#endif
  
  return [codecs copy];
}

@end

最後に、RTCPeerConnectionFactoryの初期化時にいくつかの設定を行います

#pragma mark - Lazy
- (RTCPeerConnectionFactory *)factory {
    
    
    if (!_factory) {
    
    
        RTCInitializeSSL();
        
        SDRTCVideoDecoderFactory *decoderFactory = [[SDRTCVideoDecoderFactory alloc] init];
        SDRTCVideoEncoderFactory *encoderFactory = [[SDRTCVideoEncoderFactory alloc] init];
        
//        for (RTCVideoCodecInfo *codec in encoderFactory.supportedCodecs) {
    
    
//            DebugLog(@"RTCVideoCodecInfo codec.parameters:%@", codec.parameters);
//        }
        _factory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory decoderFactory:decoderFactory];
    }
    return _factory;
}

テストの結果、画像が高解像度で表示されない問題は解決されました

V. まとめ

iOS 開発 - 高解像度の WebRTC ローカル ライブ ブロードキャストでは問題が表示されない WebRTC と ossrs を組み合わせてストリームをプッシュすると、ossrs プレーヤーで高解像度の画面が表示されないという問題が発生します。最終的に、RTCPeerConnectionFactoryのinitWithEncoderFactoryを設定することで問題を解決しました。

https://blog.csdn.net/gloryFlow/article/details/132240952

学習記録、日々改善を続けてください。

おすすめ

転載: blog.csdn.net/gloryFlow/article/details/132240952