2017-04-06 3 views
6

J'ai recherché en ligne mais il y a très peu d'informations à ce sujet.RTMP algorithme de débit adaptatif

J'ai une application de diffusion en direct où j'envoie des trames vidéo codées H264 et des morceaux audio AAC résultant de la caméra & micro en utilisant le SDK Android MediaCodec, sur une pile RTMP.

Mes flux en direct sont 720p et je vise une excellente qualité avec 2500Kbps. Cela nécessite évidemment une très bonne connexion réseau, ce qui signifie 4G si vous utilisez un plan de données.

Problème est même avec la plus grande connexion, il y aura de faibles pics et d'encombrement, de sorte qu'il y aura des moments où le réseau ne peut pas contenir un tel flux lourd. Parce que je veux offrir une grande fiabilité, je veux inclure le débit adaptatif automatique sur mon application afin que la qualité de l'image soit abandonnée en faveur ou la fiabilité.

La chose est - comment réaliser cette adaptation automatique aux conditions du réseau sans perdre les cadres? Est-ce même possible? J'ai utilisé des périphériques d'encodage professionnels comme Cerevo et ils ne perdent jamais d'images. Cependant, avec mon application, je subis toujours de terribles effets de traînage en raison de la perte d'images en p dans le réseau.

C'est ce que j'ai actuellement:

private long adaptBitrate(long idleNanos, Frame frame) { 
     int bytes = frame.getSize(); 
     long nowNanos = System.nanoTime(); 
     if (nowNanos - mLastNanos > 1000L * 1000 * 1000) { 
      double idle = (double) idleNanos/(double) (nowNanos - mLastNanos); 
      float actualBitrate = newBitrate; 

      int size = mBuffer.size(); 
      String s = "Bitrate: " + actualBitrate/1000 
        + " kbps In-Flight:" + bytes 
        + " idle: " + idle; 
      if (size > MAX_BUF_SIZE && size > mLastSize) { 
       Log.i(TAG, "adaptBitrate: Dropping bitrate"); 
       newBitrate = (int) ((double) actualBitrate * BITRATE_DROP_MULTIPLIER); 
       if (newBitrate < MIN_BITRATE) { 
        newBitrate = MIN_BITRATE; 
       } 
       s += " late => " + newBitrate; 
       mRtmpHandler.requestBitrate(newBitrate); 
      } else if (size <= 2 && idle > IDLE_THRESHOLD) { 
       mIdleFrames++; 
       if(mIdleFrames >= MIN_IDLE_FRAMES){ 
        Log.i(TAG, "adaptBitrate: Raising bitrate"); 
        newBitrate = (int) ((double) newBitrate * BITRATE_RAISE_MULTIPLIER); 
        if (newBitrate > MAX_BITRATE) { 
         newBitrate = MAX_BITRATE; 
        } 
        s += " idle => " + newBitrate; 
        mRtmpHandler.requestBitrate(newBitrate); 
        mIdleFrames = 0; 
       } 
      } 
      debugThread(Log.VERBOSE, s); 
      mLastNanos = System.nanoTime(); 
      mLastSize = size; 
      idleNanos = 0; 
     } 
     return idleNanos; 
    } 

Donc, si mon tampon dépasse un seuil, je réduire le débit. Si mon application passe trop de temps à attendre une nouvelle image, pour un nombre de trames consécutives, alors j'augmente le débit.

Même si je suis très prudent avec les valeurs de seuil, je perds toujours des informations importantes et mon flux se brise jusqu'à l'arrivée de l'image clé suivante (2 secondes). Parfois, il semble que le réseau peut contenir un certain débit (stable à 1500kbps, par exemple) mais l'image aura toujours un peu de traînée comme si une image avait été perdue dans le chemin. Avec de bonnes conditions de réseau, tout est lisse.

Comment ces périphériques de streaming gèrent-ils ces situations? Il a toujours l'air très bien avec eux, pas du tout glisser ou sauter les cadres ...

+0

Alors, savez-vous si le codeur lui-même prend en charge la commutation de mode? En d'autres termes, que se passe-t-il lorsque vous émulez un commutateur sur une connexion parfaite? En outre, s'agit-il d'un scénario de diffusion en temps réel, comme un chat ou simplement diffusé? – ThomasRS

+0

diffusion en temps réel. Je ne sais pas ce que vous entendez par "changement de mode", si vous voulez dire adapter le débit, je mesure le débit binaire de sortie et il correspond au débit souhaité, de sorte qu'il modifie effectivement le débit médian du débit binaire. De plus, tous les appareils de la version 4.3 le supportent si je ne me trompe pas. –

Répondre

0

Il n'y a en effet aucune information en ligne sur le débit adaptatif du côté du diffuseur, de manière surprenante. Quand j'ai dû implémenter quelque chose comme ça avec RTSP et deux sockets rtp, j'ai adopté une approche similaire, en créant une classe d'interrogation qui augmenterait modestement le débit du mediacodec lorsque le tampon de paquets était> $ GOOD_PCT gratuit, réduit de moitié la file d'attente était inférieur à $ BAD_PCT gratuit, et ne fait rien s'il était entre les deux. Partially seen here. Je ne suis pas sûr d'avoir une image complète de votre solution basée sur le code affiché, mais vous ajustez le débit binaire mediacodec directement, correct? La seule fois où j'ai eu de la corruption, c'est quand j'ai demandé une image de synchronisation de mediacodec, alors évitez cela si c'est dans votre code. J'espère que cela t'aides.