Exoplayer: Issue playing HLS DVR from Wowza

Created on 13 Nov 2017  路  10Comments  路  Source: google/ExoPlayer

Hi,

Before you get mad, I want to ask you kindly for help because I am newbie in development of Android apps. Please, bare with me!
THE PROBLEM:
I am trying to implement DVR in exoplayer, but the problem I have occurred is I cannot play the source video.
The source(url) is in this format:
http://<IpAddress>:<Port>/origin/<Channel>.stream/playlist.m3u8?DVR

I am using almost the basic exoplayer setup with difference of video source(HlsMediaSoruce), I have added EventListener to player in order to correct package droppings or something that cause freezing the screen.

I have entered the url in HlsMediaSource and got error: E/ACodec: [OMX.google.h264.decoder] setPortMode on output to DynamicANWBuffer failed w/ err -1010

I am looking into code example where I can see how to implement this kind of feature. So, I would ask you, why this error occurs? How to implement this feature(resource, link, hint, anything)?

I know that this is too generic question, but due to lack of experience and knowledge I couldn't be more precise and specific with my problem.

Once again, please sorry.

Thanks,
L

bad media question infeasible

All 10 comments

We're happy to help, but you still need to provide sufficient information as requested in the issue template. If you're unsure how to obtain any of the requested information, let us know and we can try and provide guidance. Thanks!

@ojw28, thanks for fast response!

I can provide code snippet of my exoplayer code(if that helps)? Please can you tell me what else do you need in order to demystify this?

The information we need is already described in the issue template you would have deleted when filing this issue. You can find it again here, although please provide the information in this issue rather than creating a new one. Thanks!

Ok, I have read that. So far I have found this pull request. But I haven't seen that this is released in any version of ExoPlayer.

Also, I have found the Class Timeline and I see that ExoPlayer supports DVR.

Here is the code example, which cannot play video with DVR.
```
if (exoPlayer != null) {
exoPlayer.release();
}
if (handler != null) {
handler.removeCallbacks(null);
}
mPlayerActivityViewModel.setMessageVisibility(false);
mMainHandler = new Handler();
mBandwidthMeter = new DefaultBandwidthMeter();
mVideoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(mBandwidthMeter, 3600000, DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, DEFAULT_BANDWIDTH_FRACTION);
mTrackSelector = new DefaultTrackSelector(mVideoTrackSelectionFactory);
mLoadControl = new DefaultLoadControl();
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, mTrackSelector);
//Player listener stuff
exoPlayer.addListener(new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.i(PLAYER_ACTIVITY_TAG, "playback state " + playbackState + " playWhenReady " + playWhenReady);
if (playbackState == Player.STATE_ENDED) {
keyTimer.cancel();
fastForwardSpeed = 10000;
Log.i(PLAYER_ACTIVITY_TAG, "Player has finished with the video!");
// to
Log.i(PLAYER_ACTIVITY_TAG, "PREPARING TO START ACTIVITY");
Intent videoEndActivity = new Intent(getApplicationContext(), VideoEndActivity.class);
startActivity(videoEndActivity);
Log.i(PLAYER_ACTIVITY_TAG, "ACTIVITY STARTED");
} else if (Player.STATE_BUFFERING == playbackState) {
playerCurrentPosition = exoPlayer.getCurrentPosition();
Log.i(PLAYER_ACTIVITY_TAG, "Player is buffering...");
Log.i(PLAYER_ACTIVITY_TAG, "Player current position: " + playerCurrentPosition);
checkIfVideoIsStuck();
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
if (isBehindLiveWindow(error)) {
setupPlayer();
Log.e(PLAYER_ACTIVITY_TAG, "BehindLiveWindowException has registred, player restarted.");
}
if (error.toString().contains("Source error")) {
Toast.makeText(PlayerActivity.this, "Source error!", Toast.LENGTH_LONG).show();
}
if (isSourceError(error)) {
Log.e(PLAYER_ACTIVITY_TAG, "SourceError has registred, player restarted.");
mPlayerActivityViewModel.setMessageText("Izvor neispravan, molimo promenite kanal!");
mPlayerActivityViewModel.setMessageVisibility(true);
}
}
@Override
public void onPositionDiscontinuity() {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
});
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
mDataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "AOC"), defaultBandwidthMeter);

    mVideoSource = new HlsMediaSource(Uri.parse("http://127.0.0.1:1359/origin/Ch1.stream/playlist.m3u8?DVR"), mDataSourceFactory, mMainHandler, new AdaptiveMediaSourceEventListener() {
        @Override
        public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) {
        }
        @Override
        public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
        }
        @Override
        public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
            Log.i(PLAYER_ACTIVITY_TAG, "onLoadCanceled");
        }
        @Override
        public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) {
        }
        @Override
        public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
            Log.i(PLAYER_ACTIVITY_TAG, "onUpstreamDiscarded");
        }
        @Override
        public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) {
            Log.i(PLAYER_ACTIVITY_TAG, "onDownstreamFormatChanged");
        }
    });
    exoPlayer.prepare(mVideoSource);
    exoPlayer.setPlayWhenReady(true);

```

As I posted earlier, the error occurs. Can you please tell me what could be the next steps? Do you need any additional informaion?

thanks,
L

The next step is for you to actually provide the information requested in our issue template.

Before filing an issue:
I have found this link, but isn't much useful due to lack of explanations how to achieve DVR with urls from wowza.
https://github.com/google/ExoPlayer/pull/2741

Unfortunately I coudn't open Demo app due to tthis issue.

Issue description

Unable to play HLS DVR from Wowza. The error that I am getting is:
E/ACodec: [OMX.google.h264.decoder] setPortMode on output to DynamicANWBuffer failed w/ err -1010
I have used the standard exoplayer setup(code you can find on the bottom of this post).

Link to test content

http://185.26.118.228:1935/origin/RTS1.stream/playlist.m3u8?DVR

Reproduction steps

Use code snippet below and HLS DVR stream from Wowza engine.

Version of ExoPlayer being used

r2.5.1

Device(s) and version(s) of Android being used

Android Emulator - Android_TV_1080p_API_26
nexus 5X API 27 emulator
nexus 5X API 26 emulator

A full bug report captured from the device

E/ACodec: [OMX.google.h264.decoder] setPortMode on output to DynamicANWBuffer failed w/ err -1010

CodeThat I have used to play this :

if (exoPlayer != null) {
exoPlayer.release();
}
if (handler != null) {
handler.removeCallbacks(null);
}
mPlayerActivityViewModel.setMessageVisibility(false);
mMainHandler = new Handler();
mBandwidthMeter = new DefaultBandwidthMeter();
mVideoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(mBandwidthMeter, 3600000, DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, DEFAULT_BANDWIDTH_FRACTION);
mTrackSelector = new DefaultTrackSelector(mVideoTrackSelectionFactory);
mLoadControl = new DefaultLoadControl();
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, mTrackSelector);
//Player listener stuff
exoPlayer.addListener(new Player.EventListener() {
@override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
@override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@override
public void onLoadingChanged(boolean isLoading) {
}
@override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.i(PLAYER_ACTIVITY_TAG, "playback state " + playbackState + " playWhenReady " + playWhenReady);
if (playbackState == Player.STATE_ENDED) {
keyTimer.cancel();
fastForwardSpeed = 10000;
Log.i(PLAYER_ACTIVITY_TAG, "Player has finished with the video!");
// to
Log.i(PLAYER_ACTIVITY_TAG, "PREPARING TO START ACTIVITY");
Intent videoEndActivity = new Intent(getApplicationContext(), VideoEndActivity.class);
startActivity(videoEndActivity);
Log.i(PLAYER_ACTIVITY_TAG, "ACTIVITY STARTED");
} else if (Player.STATE_BUFFERING == playbackState) {
playerCurrentPosition = exoPlayer.getCurrentPosition();
Log.i(PLAYER_ACTIVITY_TAG, "Player is buffering...");
Log.i(PLAYER_ACTIVITY_TAG, "Player current position: " + playerCurrentPosition);
checkIfVideoIsStuck();
}
}
@override
public void onRepeatModeChanged(int repeatMode) {
}
@override
public void onPlayerError(ExoPlaybackException error) {
if (isBehindLiveWindow(error)) {
setupPlayer();
Log.e(PLAYER_ACTIVITY_TAG, "BehindLiveWindowException has registred, player restarted.");
}
if (error.toString().contains("Source error")) {
Toast.makeText(PlayerActivity.this, "Source error!", Toast.LENGTH_LONG).show();
}
if (isSourceError(error)) {
Log.e(PLAYER_ACTIVITY_TAG, "SourceError has registred, player restarted.");
mPlayerActivityViewModel.setMessageText("Izvor neispravan, molimo promenite kanal!");
mPlayerActivityViewModel.setMessageVisibility(true);
}
}
@override
public void onPositionDiscontinuity() {
}
@override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
});
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
mDataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "AOC"), defaultBandwidthMeter);

    mVideoSource = new HlsMediaSource(Uri.parse("http://127.0.0.1:1359/origin/Ch1.stream/playlist.m3u8?DVR"), mDataSourceFactory, mMainHandler, new AdaptiveMediaSourceEventListener() {
        @Override
        public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) {
        }
        @Override
        public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
        }
        @Override
        public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
            Log.i(PLAYER_ACTIVITY_TAG, "onLoadCanceled");
        }
        @Override
        public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) {
        }
        @Override
        public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
            Log.i(PLAYER_ACTIVITY_TAG, "onUpstreamDiscarded");
        }
        @Override
        public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) {
            Log.i(PLAYER_ACTIVITY_TAG, "onDownstreamFormatChanged");
        }
    });
    exoPlayer.prepare(mVideoSource);
    exoPlayer.setPlayWhenReady(true);

Please, let me know if I need anything else to provide?

Regards,
L

You will need to inject your own HlsExtractorFactory and enable DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES. Have a look at DefaultHlsExtractorFactory for a starting point.

Depending on how this content is being generated, you may also wish to report the issue to the content provider. Media segments in HLS are supposed to contain IDR frames, and the HLS RFC states clients may discard rather than render frames prior to the first IDR (which implies discarding all frames for this kind of stream, since there aren't any IDR frames in it).

@ojw28, thank you for the answer!
I believe that the problem is with audio codec since the audio codec that I have used before was
CODECS="avc1.100.30,mp4a.40.2" and everything worked fine, and now is CODECS="avc1.77.30,mp4a.40.33".

From your experience, can this cause the problem?
Thanks,
L

It seems you have also changed the video profile. Have you actually re-encoded the content? Or did you just change the manifest?

Was this page helpful?
0 / 5 - 0 ratings