Search code examples
androidstreaminghttp-live-streamingm3u8

Android HLS- Streaming failed to fetch segment


I write a Videoplayer for Android to stream Video over HLS. On my Server I have the m3u8-Playlist and the .ts-Segments. My Code look like this:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    vidSurface = (SurfaceView) findViewById(R.id.surfView);
    vidHolder = vidSurface.getHolder();
    vidHolder.addCallback(this);
}


public void surfaceCreated(SurfaceHolder arg0) {
    try {
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDisplay(vidHolder);
        mediaPlayer.setDataSource(vidAddress);
        mediaPlayer.prepareAsync();
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    }
    catch(Exception e){
        e.printStackTrace();
    }
}    

The Player works fine for the Apple bipbopall.m3u8 example. But when I try to play my Playlist this error occurs:

E/PlaylistFetcher﹕ failed to fetch .ts segment at url 'http://example.com/USSM.mp4Frag1Num0.ts'
E/LiveSession﹕ XXX Received error -1008 from PlaylistFetcher.
E/MediaPlayer﹕ error (1, -1008)

I think there is a problem with the AES-128 decryption of the files. Does the MediaPlayer decrypt the files by him self and how can I check if the decryption was successful? (I use the latest Android-Version)


Solution

  • To resume the discussion in the comments:

    1008 is ERROR_OUT_OF_RANGE returned when trying to read the segment into a buffer. Check if the server is properly responding by downloading a segment, decrypting it and attempting to play it back (see method below).

    Other things to check: make sure the MPEG-TS segments are valid. If you used the H.264 stream contained in an MP4 file to create the segments check if they're using the Annex B format (for eg. in ffmpeg you can use the h264_mp4toannexb bitstream filter which works on the encoded stream - you can use it with -c:v copy)

    To check if the encryption is correct use openssl.

    1. Get the key in plain hex

      xxd -p keyfile.key

    2. Decrypt a .ts segment

      openssl aes-128-cbc -d -in encrypted_segment.ts -out decrypted_segment.ts -nosalt -iv <iv_hex> -K <key_hex>
      

      If there's no defined IV then it is equal to the media sequence.

    3. Attempt to play back the decrypted segment.