Llamada de audio y video WebRTC: la alta resolución local en vivo de WebRTC no muestra el problema de la pantalla

Desarrollo de iOS: la alta resolución local en vivo de WebRTC no muestra el problema de la pantalla

Al usar WebRTC combinado con ossrs para impulsar la transmisión antes, el reproductor de ossrs no podía ver el problema de las imágenes de alta resolución. Según esta pregunta, se encontró una solución.

1. ¿Qué es WebRTC?

¿Qué es WebRTC?

WebRTC (Web Real-Time Communications) es una tecnología de comunicación en tiempo real que permite que aplicaciones o sitios de red establezcan una conexión peer-to-peer (Peer-to-Peer) entre navegadores sin intermediarios para lograr el streaming y/o la transmisión de vídeo. de transmisiones de audio u otros datos arbitrarios.

2. ¿Qué es ossrs?

que es ossrs
SRS (Simple Realtime Server) es un servidor de vídeo en tiempo real simple y eficiente que admite múltiples protocolos de medios de transmisión en tiempo real, como RTMP, WebRTC, HLS, HTTP-FLV y SRT.

Dirección del sitio web oficial: https://ossrs.net/lts/zh-cn/

Aquí no escribiré sobre iOS, Google WebRTC y ossrs para implementar la transmisión en vivo de RTC. Por el momento, vale la pena registrar el problema de que la transmisión en vivo WebRTC local de alta resolución no muestra la imagen.

3. Solución al problema de no mostrar pantalla en alta resolución

El problema de que la transmisión en vivo de alta resolución en vivo de WebRTC local no muestra la imagen está relacionado con el ID de nivel de perfil en el SDP.

perfil-nivel-id es exactamente la codificación base16 del segundo al cuatro bytes en SPS. El significado específico de estos tres bytes es

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

Cuando http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Levels
está realmente configurado, el valor del nivel se multiplica por 10, por ejemplo, nivel 1.0, el valor establecido es 0x0A. nivel 3.0, el valor de configuración es 0x1E. La excepción es el nivel 1b, el valor de configuración es 0x09

Red de origen de imágenes (lo siento, olvidé la dirección, si cita la imagen de su blog, deje un mensaje)
inserte la descripción de la imagen aquí

El tercero representa el nivel, por ejemplo, el valor de 1f es 31. Se puede ver en la figura que es 3.1 y la resolución es 720 480 720 576 1280 * 720

Si necesita alta resolución 1920 1080 2560 1920 3840*2160, debe establecer el valor hexadecimal del nivel 5.1 en 33, el valor establecido aquí es 42e033.

A continuación se muestra un ejemplo de SDP

“código”: 0,
“servidor”: “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=group:BUNDLE 0 1\r\na=msid-semantic: WMS en vivo/livestream\r\nm=audio 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=huella digital: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:pasivo\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=candidate:0 1 udp 2130706431 10.0.80.128 8000 generación de host tipo 0\r\na=candidate:1 1 udp 2130706431 112.124.157.141 8000 generación de host tipo 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=huella digital: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 transporte-cc\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=fmtp:96 nivel-asimetría-permitido= 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 tipo de generación de host 0\r\na= candidato:1 1 udp 2130706431 112.124.157.141 8000 tipo generación de host 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 transporte-cc\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=fmtp:96 nivel-asimetría- permitido=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 tipo generación de host 0\r\ na=candidato:1 1 udp 2130706431 112.124.157.141 8000 tipo generación de host 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 transporte-cc\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=fmtp:96 nivel-asimetría- permitido=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 tipo generación de host 0\r\ na=candidato:1 1 udp 2130706431 112.124.157.141 8000 tipo generación de host 0\r\n”,141 8000 generación de host tipo 0\r\n”,141 8000 generación de host tipo 0\r\n”,
“id de sesión”: “q01184s8:oPvh”
}

Puedes ver perfil-level-id=42e01f aquí

Si reemplaza el ID de nivel de perfil del SDP local con 42e033 en WebRTC

[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];
    }];

Cambie el ID de nivel de perfil en el SDPString remoto obtenido llamando a la interfaz rtc/v1/publish/ a 42e033 antes de llamar

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

Después de la prueba, el cambio de imágenes de alta resolución se puede mostrar normalmente.

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. Resuelva el problema de la alta resolución que no muestra la pantalla a través de RTCVideoEncoderFactory

Cambiar el ID de nivel de perfil en el SDP no es mi solución final. Finalmente uso el valor de ID de nivel de perfil de constrainedHighParams en RTCVideoCodecInfo de RTCVideoEncoder especificando 42e033.

Establezca los elementos constrainedHighInfo y constrainedBaselineInfo de los códecs.

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];

El código completo es el siguiente.

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

Finalmente, realice algunas configuraciones cuando se inicialice 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;
}

Después de las pruebas, se solucionó el problema de no mostrar la imagen en alta resolución.

V. Resumen

Desarrollo de iOS: el video local en vivo de alta resolución de WebRTC no muestra el problema; cuando se usa WebRTC combinado con ossrs para impulsar la transmisión, el reproductor de ossrs no puede ver el problema del video de alta resolución. Finalmente resolvió el problema configurando initWithEncoderFactory de RTCPeerConnectionFactory.

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

Registros de aprendizaje, sigue mejorando cada día.

Supongo que te gusta

Origin blog.csdn.net/gloryFlow/article/details/132240952
Recomendado
Clasificación