2017-03-12 164 views
2

使用Exoplayer,我試圖從一個字節數組播放音頻文件。我試圖用ByteArrayDataSource,但我得到調用構造函數時出現錯誤:new ByteArrayDataSource(data); 這裏是我想出來的代碼:Exoplayer從字節數組播放音頻 - ByteArrayDataSource

private void prepareExoPlayerFromByteArray(byte[] data){ 
     exoPlayer = ExoPlayerFactory.newSimpleInstance(this, new DefaultTrackSelector(null), new DefaultLoadControl()); 
     exoPlayer.addListener(eventListener); 


     final ByteArrayDataSource byteArrayDataSource = new ByteArrayDataSource(data); 

     /* 
     DataSpec dataSpec = new DataSpec(byteArrayDataSource.getUri()); 
     try { 
      byteArrayDataSource.open(dataSpec); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     */ 

     DataSource.Factory factory = new DataSource.Factory() { 
      @Override 
      public DataSource createDataSource() { 
       return byteArrayDataSource; 
      } 
     }; 

     MediaSource audioSource = new ExtractorMediaSource(byteArrayDataSource.getUri(), 
       factory, new DefaultExtractorsFactory(),null,null); 
     exoPlayer.prepare(audioSource); 
    } 

我得到的錯誤是這樣的:

E/ExoPlayerImplInternal: Internal runtime error. 
                       java.lang.NullPointerException 
                        at com.google.android.exoplayer2.util.Assertions.checkNotNull(Assertions.java:107) 
                        at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractingLoadable.<init>(ExtractorMediaPeriod.java:591) 
                        at com.google.android.exoplayer2.source.ExtractorMediaPeriod.startLoading(ExtractorMediaPeriod.java:452) 
                        at com.google.android.exoplayer2.source.ExtractorMediaPeriod.prepare(ExtractorMediaPeriod.java:165) 
                        at com.google.android.exoplayer2.ExoPlayerImplInternal.maybeUpdateLoadingPeriod(ExoPlayerImplInternal.java:1260) 
                        at com.google.android.exoplayer2.ExoPlayerImplInternal.updatePeriods(ExoPlayerImplInternal.java:1102) 
                        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:447) 
                        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300) 
                        at android.os.Handler.dispatchMessage(Handler.java:98) 
                        at android.os.Looper.loop(Looper.java:234) 
                        at android.os.HandlerThread.run(HandlerThread.java:61) 
                        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40) 

該錯誤似乎來自ByteArrayDataSource的構造函數,並且傳遞給它的數據爲空,它不是我在調用它之前檢查的,並且該數組中有14002427個字節。

/** 
    * @param data The data to be read. 
    */ 
    public ByteArrayDataSource(byte[] data) { 
    Assertions.checkNotNull(data); 
    Assertions.checkArgument(data.length > 0); 
    this.data = data; 
    } 

什麼我做錯了,我怎麼圍繞它得到什麼?有沒有人有一個通過傳遞字節數組作爲源與Exoplayer播放音頻文件的工作示例?

+0

@pskink即使我沒有使用的MediaPlayer,你建議的方法不採取字節數組。無關tho,因爲我需要使用Exoplayer來做到這一點。 – ak93

+0

任何解決方案?我面臨完全相同的問題 – Chandru

+0

請參考下面的答案,如果可以的話,請注意。謝謝你:) – RaghavPai

回答

0

byteArrayDataSource.getUri()將是零,如果你不叫

byteArrayDataSource.open(DataSpec dataSpec)。看代碼;

public final class ByteArrayDataSource implements DataSource { 

    private final byte[] data; 

    private Uri uri; 
    private int readPosition; 
    private int bytesRemaining; 

    /** 
    * @param data The data to be read. 
    */ 
    public ByteArrayDataSource(byte[] data) { 
    Assertions.checkNotNull(data); 
    Assertions.checkArgument(data.length > 0); 
    this.data = data; 
    } 

    @Override 
    public long open(DataSpec dataSpec) throws IOException { 
    uri = dataSpec.uri; 
    readPosition = (int) dataSpec.position; 
    bytesRemaining = (int) ((dataSpec.length == C.LENGTH_UNSET) 
     ? (data.length - dataSpec.position) : dataSpec.length); 
    if (bytesRemaining <= 0 || readPosition + bytesRemaining > data.length) { 
     throw new IOException("Unsatisfiable range: [" + readPosition + ", " + dataSpec.length 
      + "], length: " + data.length); 
    } 
    return bytesRemaining; 
    } 

    @Override 
    public int read(byte[] buffer, int offset, int readLength) throws IOException { 
    if (readLength == 0) { 
     return 0; 
    } else if (bytesRemaining == 0) { 
     return C.RESULT_END_OF_INPUT; 
    } 

    readLength = Math.min(readLength, bytesRemaining); 
    System.arraycopy(data, readPosition, buffer, offset, readLength); 
    readPosition += readLength; 
    bytesRemaining -= readLength; 
    return readLength; 
    } 

    @Override 
    public Uri getUri() { 
    return uri; 
    } 

    @Override 
    public void close() throws IOException { 
    uri = null; 
    } 

} 
0
class UriByteDataHelper { 


     public Uri getUri(byte[] data) { 

      try { 
       URL url = new URL(null, "bytes:///" + "audio", new BytesHandler(data)); 
       return Uri.parse(url.toURI().toString()); 
      } catch (MalformedURLException e) { 
       throw new RuntimeException(e); 
      } catch (URISyntaxException e) { 
       throw new RuntimeException(e); 
      } 

     } 

     class BytesHandler extends URLStreamHandler { 
      byte[] mData; 
      public BytesHandler(byte[] data) { 
       mData = data; 
      } 

      @Override 
      protected URLConnection openConnection(URL u) throws IOException { 
       return new ByteUrlConnection(u, mData); 
      } 
     } 

     class ByteUrlConnection extends URLConnection { 
      byte[] mData; 
      public ByteUrlConnection(URL url, byte[] data) { 
       super(url); 
       mData = data; 
      } 

      @Override 
      public void connect() throws IOException { 
      } 

      @Override 
      public InputStream getInputStream() throws IOException { 

       return new ByteArrayInputStream(mData); 
      } 
     } 
    } 



    private void prepareExoPlayerFromByteArray(byte[] data){ 
     exoPlayer = ExoPlayerFactory.newSimpleInstance(this, new DefaultTrackSelector(null), new DefaultLoadControl()); 
     exoPlayer.addListener(eventListener); 

     final MByteArrayDataSource byteArrayDataSource = new MByteArrayDataSource(data); 
     Log.i(TAG,"ByteArrayDataSource constructed."); 
     Uri audioByteUri = new UriByteDataHelper().getUri(data); 
     DataSpec dataSpec = new DataSpec(audioByteUri); 
     try { 
      byteArrayDataSource.open(dataSpec); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 


     DataSource.Factory factory = new DataSource.Factory() { 
      @Override 
      public DataSource createDataSource() { 
       return byteArrayDataSource; 
      } 
     }; 
     Log.i(TAG,"DataSource.Factory constructed."); 


     MediaSource audioSource = new ExtractorMediaSource(audioByteUri, 
       factory, new DefaultExtractorsFactory(),null,null); 
     Log.i(TAG,"Audio source constructed."); 
     exoPlayer.prepare(audioSource); 
     initMediaControls(); 
    } 
+0

使用上面的代碼來創建Uri直接從字節數組中播放音頻數據....讓我知道是否有任何問題。 – RaghavPai