2016-06-12 26 views
10

Chciałbym pobrać wideo, które jest przesyłane strumieniowo w ExoPlayer.Android ExoPlayer - pobieranie wideo (bez DASH/HLS) i przesyłanie strumieniowe w tym samym czasie

Odkładając na bok, a nawet przed użyciem ExoPlayer, pobrałem plik ze strumienia wejściowego dostarczonego przez HttpURLConnection i odtworzyłem plik z pamięci lokalnej. To jest w porządku, ale nie rozwiązuje mojego problemu jednoczesnego przesyłania strumieniowego i buforowania.

ExoPlayer zapewnia również system buforowania, który działa tylko w przypadku strumieni DASH lub HLS. Korzystam z żadnego z nich i chcę buforować mp4 z ExtractorRendererBuilder. (Ten temat jest omówiony dość obszernie tutaj: https://github.com/google/ExoPlayer/issues/420).

DefaultHttpDataSource ma api, który eksponuje HttpURLConnection, ale nie jestem pewien, czy używam ponownie strumienia. Oto kod z próbek dostarczonych w ExoPlayer.

@Override 
    public void buildRenderers(DemoPlayer player) { 
     Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE); 
     Handler mainHandler = player.getMainHandler(); 

     // Build the video and audio renderers. 
     DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(mainHandler, null); 
     DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter,userAgent); 
     ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri,dataSource,allocator, 
       BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE, mainHandler, player, 0); 
     MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context, 
       sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000, 
       mainHandler, player, 50); 
     MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, 
       MediaCodecSelector.DEFAULT, null, true, mainHandler, player, 
       AudioCapabilities.getCapabilities(context), AudioManager.STREAM_MUSIC); 
     TrackRenderer textRenderer = new TextTrackRenderer(sampleSource, player, 
       mainHandler.getLooper()); 

     // Invoke the callback. 
     TrackRenderer[] renderers = new TrackRenderer[DemoPlayer.RENDERER_COUNT]; 
     renderers[DemoPlayer.TYPE_VIDEO] = videoRenderer; 
     renderers[DemoPlayer.TYPE_AUDIO] = audioRenderer; 
     renderers[DemoPlayer.TYPE_TEXT] = textRenderer; 
     player.onRenderers(renderers, bandwidthMeter); 
    } 

Co mam zrobić teraz to przedłużyć DefaultHttpDataSource i używać HttpURLConnection uzyskać InputStream, zapis do pliku w getCacheDir(). Tutaj jest klasa, która rozszerza DefaultHttpDataSource:

public class CachedHttpDataSource extends DefaultHttpDataSource { 
    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate) { 
     super(userAgent, contentTypePredicate); 
    } 

    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, TransferListener listener) { 
     super(userAgent, contentTypePredicate, listener); 
    } 

    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, TransferListener listener, int connectTimeoutMillis, int readTimeoutMillis) { 
     super(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis); 
    } 

    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, TransferListener listener, int connectTimeoutMillis, int readTimeoutMillis, boolean allowCrossProtocolRedirects) { 
     super(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis, allowCrossProtocolRedirects); 
    } 

    public HttpURLConnection getURLConnection(){ 
     HttpURLConnection connection = getConnection(); 

     return getConnection(); 
    } 
} 

mogę teraz dostać InputStream poprzez getURLConnection(), aby zapisać film do pliku, ale nie jestem naprawdę zadowolony z wykorzystaniem InputStream ponownie do buforowania wideo. Czy istnieje inny interfejs API lub metoda, która daje dostęp do tablicy bajtów, którą mogę zapisać do pliku podczas przesyłania strumieniowego?

Moi Inne wyszukiwania StackOverflow nie dały rozwiązanie jeszcze:

Using cache in ExoPlayer

ExoPlayer cache

Dziękuję za poświęcony czas i cierpliwość.

Odpowiedz

2

Znalazłem rozwiązanie z tylko jednym problemem: szukanie w tył lub w przód nie działa.

To jest kawałek kodu:

public void preparePlayer(String videoUri) { 
    MediaSource videoSource = 
      new ExtractorMediaSource(Uri.parse(videoUri), dataSourceFactory, extractorsFactory, handler, null); 
    exoPlayer.prepare(videoSource); 
    exoPlayer.setPlayWhenReady(true); 
} 

public DataSource.Factory buildDataSourceFactory() { 
    return new DataSource.Factory() { 
     @Override 
     public DataSource createDataSource() { 
      LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(CACHE_SIZE_BYTES); 
      File cacheDir = //Your cache dir 
      SimpleCache simpleCache = new SimpleCache(cacheDir, evictor); 
      DataSource dataSource = buildMyDataSourceFactory().createDataSource(); 
      int cacheFlags = CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_CACHE_UNBOUNDED_REQUESTS; 
      return new CacheDataSource(simpleCache, dataSource, cacheFlags, CACHE_SIZE_BYTES); 
     } 
    }; 
} 

private DefaultDataSource.Factory buildMyDataSourceFactory() { 
    return new DefaultDataSourceFactory(context, "jesty-android", new DefaultBandwidthMeter()); 
} 

Źródło: https://github.com/google/ExoPlayer/issues/420#issuecomment-244652023