Extracting metadata from Icecast stream using Exoplayer

后端 未结 5 1912
旧时难觅i
旧时难觅i 2021-01-07 02:31

Since switching from Mediaplayer to a simple implementation Exoplayer I have noticed much improved load times but I\'m wondering if there is any built in functionality such

5条回答
  •  北恋
    北恋 (楼主)
    2021-01-07 03:28

    I have an AsyncTask that starts ExoPlayer from an IceCast Stream:

    OkHttpClient okHttpClient = new OkHttpClient();
    
    UriDataSource uriDataSource = new OkHttpDataSource(okHttpClient, userAgent, null, null, CacheControl.FORCE_NETWORK);
    ((OkHttpDataSource) uriDataSource).setRequestProperty("Icy-MetaData", "1");
    ((OkHttpDataSource) uriDataSource).setPlayerCallback(mPlayerCallback);
    
    DataSource dataSource = new DefaultUriDataSource(context, null, uriDataSource);
    
    ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, allocator,
                        BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
    
    
    MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource,
    MediaCodecSelector.DEFAULT, null, true, null, null,
    AudioCapabilities.getCapabilities(context), AudioManager.STREAM_MUSIC);
    mPlayerCallback.playerStarted();
    exoPlayer.prepare(audioRenderer);
    

    OkHttpDataSource is the class that implements HttpDataSource using OkHttpClient. It creates InputStream as a response from a request. I included this class from AACDecoder library https://github.com/vbartacek/aacdecoder-android/blob/master/decoder/src/com/spoledge/aacdecoder/IcyInputStream.java and replace InputStream with IcyInputStream depending on the response:

    (In open() of OkHttpDataSource)

    try {
      response = okHttpClient.newCall(request).execute();
      responseByteStream = response.body().byteStream();
    
      String icyMetaIntString = response.header("icy-metaint");
      int icyMetaInt = -1;
      if (icyMetaIntString != null) {
        try {
          icyMetaInt = Integer.parseInt(icyMetaIntString);
          if (icyMetaInt > 0)
            responseByteStream = new IcyInputStream(responseByteStream, icyMetaInt, playerCallback);
        } catch (Exception e) {
          Log.e(TAG, "The icy-metaint '" + icyMetaInt + "' cannot be parsed: '" + e);
        }
      }
    
    } catch (IOException e) {
      throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e,
          dataSpec);
    }
    

    Now IcyInputStream can catch the medatada and invoke callback object (playerCallback here). PlayerCallback is also from the AACDecoder library: https://github.com/vbartacek/aacdecoder-android/blob/b58c519a341340a251f3291895c76ff63aef5b94/decoder/src/com/spoledge/aacdecoder/PlayerCallback.java

    This way you are not making any duplicate stream and it is singular. If you don't want to have AACDecoder library in your project, then you can just copy needed files and include them directly in your project.

提交回复
热议问题