Reproducción de HLS con ExoPlayer

Estoy intentando crear una visión muy simple extendiendo SurfaceView y haciendo el vídeo de ExoPlayer a su superficie. Quiero apoyar HLS y SÓLO HLS. Parece que obtener el audio de forma coherente, pero nunca veo vídeo prestados a la pantalla. Tengo curiosidad por lo que podría estar haciendo mal.

El único error que veo en mi Logcat es el siguiente:

E/OMXMaster﹕ A component of name 'OMX.qcom.audio.decoder.aac' already exists, ignoring this one. 

A continuación se muestra mi código.

 private static final int BUFFER_SEGMENT_SIZE = 256 * 1024; private static final int BUFFER_SEGMENTS = 64; private ExoPlayer mExoPlayer; private Handler mHandler; private AudioCapabilitiesReceiver mAudioCapabilitiesReceiver; private AudioCapabilities mAudioCapabilities; private ManifestFetcher<HlsPlaylist> playlistFetcher; private String mUserAgent; String url = "http://solutions.brightcove.com/bcls/assets/videos/Great-Blue-Heron.m3u8"; public ExoPlayerView(Context context) { super(context); } public ExoPlayerView(Context context, AttributeSet attrs) { super(context, attrs); } public ExoPlayerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void init() { mHandler = new Handler(); mUserAgent = Util.getUserAgent(getContext(), "CX Video Player"); HlsPlaylistParser parser = new HlsPlaylistParser(); playlistFetcher = new ManifestFetcher<>(url, new DefaultUriDataSource(getContext(), mUserAgent), parser); mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(getContext(), this); mAudioCapabilitiesReceiver.register(); } @Override public void play() { mExoPlayer.setPlayWhenReady(true); } @Override public void stop() { mExoPlayer.stop(); release(); } @Override public void pause() { mExoPlayer.setPlayWhenReady(false); } @Override public void seekTo(long timeMillis) { mExoPlayer.seekTo(timeMillis); } @Override public long getCurrentPosition() { return mExoPlayer.getCurrentPosition(); } @Override public boolean isPlaying() { return false; } @Override public void playNext() { } @Override public boolean isPlayingLastVideo() { return false; } @Override public int getDuration() { return (int)mExoPlayer.getDuration(); } @Override public void addVideo(Uri uri) { } @Override public void addVideos(List<Uri> uris) { } @Override public void release() { mAudioCapabilitiesReceiver.unregister(); mExoPlayer.release(); } @Override public void onSingleManifest(HlsPlaylist hlsPlaylist) { final int numRenderers = 2; LoadControl loadControl = new DefaultLoadControl(new DefaultAllocator(BUFFER_SEGMENT_SIZE)); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); int[] variantIndices = null; if (hlsPlaylist instanceof HlsMasterPlaylist) { HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) hlsPlaylist; try { variantIndices = VideoFormatSelectorUtil.selectVideoFormatsForDefaultDisplay( getContext(), masterPlaylist.variants, null, false); } catch (MediaCodecUtil.DecoderQueryException e) { e.printStackTrace(); return; } if (variantIndices.length == 0) { return; } } DataSource dataSource = new DefaultUriDataSource(getContext(), bandwidthMeter, mUserAgent); HlsChunkSource hlsChunkSource = new HlsChunkSource(dataSource, url, hlsPlaylist, bandwidthMeter, variantIndices, HlsChunkSource.ADAPTIVE_MODE_SPLICE, mAudioCapabilities); HlsSampleSource hlsSampleSource = new HlsSampleSource(hlsChunkSource, loadControl, BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE); // Build the track renderers TrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(hlsSampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); TrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(hlsSampleSource); // Build the ExoPlayer and start playback mExoPlayer = ExoPlayer.Factory.newInstance(numRenderers); mExoPlayer.prepare(videoRenderer, audioRenderer); // Pass the surface to the video renderer. mExoPlayer.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, getHolder().getSurface()); mExoPlayer.setPlayWhenReady(true); } @Override public void onSingleManifestError(IOException e) { } @Override public void onAudioCapabilitiesChanged(AudioCapabilities audioCapabilities) { mAudioCapabilities = audioCapabilities; playlistFetcher.singleLoad(mHandler.getLooper(), this); } } 

Así que encontré mi problema. Después de volver a través del código de demostración, me di cuenta de que la demo SurfaceView se envolvió en com.google.android.exoplayer.AspectRatioFrameLayout. Después de envolver mi SurfaceView en este mismo diseño, el video comenzó mágicamente a jugar.

Tuve una situación similar en la que podía escuchar el audio, pero no de vídeo, sólo una pantalla en negro. Resulta que estaba tratando de enviar el mesagge de superficie establecida:

 player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface); 

Antes de que el procesamiento de vídeo fue realmente inicializado y listo, es por eso que sólo podía escuchar audio

  • ExoPlayer no reproduce audio en los dispositivos que utilizan FFMPEG
  • Intentar trabajar con ExoPlayer - muchas incógnitas
  • Cómo implementar oncompletionlistener para detectar final de archivo multimedia en Exoplayer
  • Android - ExoPlayer2 subtítulos
  • ExoPlayer deja de jugar en segundo plano
  • Silenciar audio en ExoPlayer
  • Creación de una instancia sencilla de ExoPlayer
  • Cómo usar android exoplayer
  • Listador de la lista de reproducción de ExoPlayer 2
  • ExoPlayer - cómo reproducir archivos mp3 locales
  • Vídeo de escala de matriz en TextureView Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.