2017-07-24 4 views
0

ich meine eigene MediaDataSource haben:
MediaExtractor nicht versteht Audio/AACP Streams



    class MyDataSource extends MediaDataSource { 
     private static final String TAG = "MyDataSource"; 
     private HttpURLConnection connection; 
     private BufferedInputStream inputStream; 

     MyDataSource(@NonNull URL streamURL) throws Throwable { 
      this.connection = (HttpURLConnection) streamURL.openConnection(); 
      this.connection.setRequestMethod("GET"); 
      this.connection.addRequestProperty("Icy-Metadata", "0"); 
      this.connection.connect(); 
      int responseCode = this.connection.getResponseCode(); 
      if (responseCode != 200) 
       throw new IOException("http response code " + responseCode); 
      for (Map.Entry<String, List<String>> header: this.connection.getHeaderFields().entrySet()) { 
       for (String headerValue : header.getValue()) 
        Log.v(TAG, "responseHeader(" + header.getKey() + ") = \"" + headerValue + "\""); 
      } 
      this.inputStream = new BufferedInputStream(connection.getInputStream()); 
     } 

     @Override 
     public long getSize() { 
      return -1; 
     } 

     @Override 
     public int readAt(long position, @NonNull byte[] buffer, int offset, int size) throws IOException { 
      int bytesRead; 
      int bytesReadTotal = 0; 
      do { 
       bytesRead = this.inputStream.read(buffer, offset + bytesReadTotal, size - bytesReadTotal); 
       bytesReadTotal += bytesRead; 
      } while(bytesRead != 0 && bytesReadTotal < size); 
      return bytesReadTotal; 
     } 

     @Override 
     public void close() { 
      try { 
       if (inputStream != null) { 
        inputStream.close(); 
        inputStream = null; 
       } 
       if (connection != null) { 
        connection.disconnect(); 
        connection = null; 
       } 
      } catch(IOException e) { 
       Log.e(TAG, "close", e); 
      } 
     } 
    } 

Und wenn ich versuche, MP3 Stream zu spielen (ex A.0.0.00Radio.):



    MyDataSource dataSource = new MyDataSource(new URL("http://streaming.shoutcast.com/80sPlanet")); 
    MediaExtractor mediaExtractor = new MediaExtractor(); 
    mediaExtractor.setDataSource(); 
    MediaFormat mediaFormat = mediaExtractor.getTrackFormat(0); 
    String mime = mediaFormat.getString(MediaFormat.KEY_MIME); 
    Log.v("Player", "mime: " + mime); 
    mediaExtractor.selectTrack(0); 
    MediaCodec mediaCodec = MediaCodec.createDecoderByType(mime); 
    mediaCodec.configure(this.mediaFormat, null, null, 0); 
    int sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE); 
    AudioTrack audioTrack = new AudioTrack(
     AudioManager.STREAM_MUSIC, 
     sampleRate, 
     AudioFormat.CHANNEL_OUT_STEREO, 
     AudioFormat.ENCODING_PCM_16BIT, 
     AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT), 
     AudioTrack.MODE_STREAM); 
    mediaCodec.setCallback(new MyCodecCallback()); 
    mediaCodec.start(); 
    audioTrack.play(); 

I siehe die folgenden Logcat trace:

 

    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(null) = "HTTP/1.1 200 OK" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Access-Control-Allow-Headers) = "Origin, Accept, X-Requested-With, Content-Type" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Access-Control-Allow-Methods) = "GET, OPTIONS, HEAD" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Access-Control-Allow-Origin) = "*" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Cache-Control) = "no-cache, no-store" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Connection) = "close" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Content-Type) = "audio/mpeg" 
    07-24 18:11:49.958 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Date) = "Mon, 24 Jul 2017 18:11:59 GMT" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Expires) = "Mon, 26 Jul 1997 05:00:00 GMT" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-br) = "128" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-genre) = "Decades,80s" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-name) = "A.0.0.00Radio:All 80s All The Time" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-notice1) = "<BR>This stream requires <a href="http://www.winamp.com">Winamp</a><BR>" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-notice2) = "SHOUTcast DNAS/posix(linux x64) v2.5.1.725<BR>" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-pub) = "1" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-sr) = "44100" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(icy-url) = "http://a.0.00radio.com/80s/" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Pragma) = "no-cache" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(Server) = "Icecast 2.3.3-kh8" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Received-Millis) = "1500919909958" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Response-Source) = "NETWORK 200" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Selected-Protocol) = "http/1.1" 
    07-24 18:11:49.959 7408-7671/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Sent-Millis) = "1500919909816" 
    07-24 18:11:49.961 7408-7671/com.sample.sandbox E/WVMExtractor: Failed to open libwvm.so: dlopen failed: library "libwvm.so" not found 
    07-24 18:11:49.962 7408-7671/com.sample.sandbox V/Player: mime: audio/mpeg 
    07-24 18:11:49.964 7408-7681/com.sample.sandbox I/OMXClient: Using client-side OMX mux. 
    07-24 18:11:50.170 7408-7681/com.sample.sandbox I/MediaCodec: MediaCodec will operate in async mode 
    [...] 

Es scheint, dass alles in Ordnung ist (der Stream spielt tatsächlich durch das Gerät).
Aber wenn ich versuche, AAC Strom zu öffnen (ex COOLfahrenheit 93.):

 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(null) = "HTTP/1.0 200 OK" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(content-type) = "audio/aacp" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-br) = "128" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-genre) = "Easy Listening, Pop" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-name) = "COOLfahrenheit 93 - (4)" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-notice1) = "<BR>This stream requires <a href="http://www.winamp.com">Winamp</a><BR>" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-notice2) = "SHOUTcast DNAS/posix(linux x64) v2.4.7.256<BR>" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-pub) = "1" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(icy-url) = " http://www.coolism.net " 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Received-Millis) = "1500921523862" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Response-Source) = "NETWORK 200" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Selected-Protocol) = "http/1.0" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(X-Android-Sent-Millis) = "1500921523387" 
    07-24 18:38:43.863 32284-32690/com.sample.sandbox V/MyDataSource: responseHeader(X-Clacks-Overhead) = "GNU Terry Pratchett" 
    07-24 18:38:45.424 32284-32690/com.sample.sandbox E/WVMExtractor: Failed to open libwvm.so: dlopen failed: library "libwvm.so" not found 
    07-24 18:38:45.425 32284-32690/com.sample.sandbox E/PlayerThread: error 
                       java.io.IOException: Failed to instantiate extractor. 
                        at android.media.MediaExtractor.setDataSource(Native Method) 
                        at com.sample.sandbox.Player.open(Player.java:204) 
                        at com.sample.sandbox.Player.<init>(Player.java:231) 
                        at com.sample.sandbox.PlayerThread.run(PlayerThread.java:28) 

Weiß jemand, was ist das Problem:



    MyDataSource dataSource = new MyDataSource(new URL("http://111.223.51.8:8005")); 
    [...] 

die MediaExtractor verrückt wird? Das Problem ist definitiv nicht im Stream selbst - es ist voll gültig.

Antwort

0

Mein Hauptfehler war das position Argument der MediaDataSource::readAt() Methode zu ignorieren.
Es stellte sich heraus, dass MediaExtractor eine Menge von Sprüngen durch die Datei (vorwärts als auch rückwärts! - und das ist sehr ärgerlich, wenn Sie HLS streamen).
Mir ist aufgefallen, dass die Anzahl dieser Überspringungen (und deren Reichweite) vom Inhaltstyp sowie vom jeweiligen Codec abhängt. Und mein Hauptpunkt in dieser Frage war "MediaExtractor versteht nicht aacp", weil AAC Codec stark das Überspringen erfordert, aber MP3 Codec nicht.