18

I realise that there are some issues in terms of level of support of HLS in Android. I'm trying to write a small videoplayer demo (to work on as many devices as possible); preferably without using a third party library; that can stream HLS video.

NOTE: I'm currently testing on JellyBean 4.2.2, but have access to other versions

I have managed to use the MediaPlayer class so that my app is able to start playing a stream (eg Apple's test video BipBopAll), but it seems to be loading the wrong section of the stream, as the video seems to start at 29 minutes in (and so it finishes after about thirty seconds).

The code that I've used is pretty basic:

private void playTrack()
{   
    player = new MediaPlayer();

    try 
    {                   
        player.setDisplay(holder);
        player.setDataSource("http://devimages.apple.com/iphone/samples/bipbop
                              /bipbopall.m3u8");
        player.prepare();

    } 
    catch (...) 
    {
    }
    player.start();
}

Update: I've tested the same code on ICS 4.0.4, and it works correctly. Testing in 3.0.1, loads the stream at 15 minutes, and then runs correctly from there.

What can I do to ensure that the stream starts at the beginning, and plays correctly on multiple Android versions?

Or, is there a better implementation that I should use?

HaemEternal
  • 2,229
  • 6
  • 31
  • 50

4 Answers4

14

Following some further investigation, I've found the following information that can hopefully help other people get HLS streaming on Android working.

Encoding - The video encoding, and the segmentation setup can have a large impact on the Android versions that the video supports. I ended up creating a video using HandBrake, with the following settings:

  • MP4 File
  • H.264; Baseline Profile; Level 3
  • AAC Audio; 44.1k; 128bit (Note: I found that JellyBean was a lot more picky about the audio than ICS/Honeycomb. Some audio bitrates would create videos that Jellybean would not play at all. In general Mono and low bitrate audio seemed to work better on Jellybean).

Segmentation - Using the Apple MediaFileSegmenter, I found adding the "-no-floating-point-duration" and "-z none" flags allowed me to create a video that worked across Android 3.0->4.2

Gingerbread - I was unable to get Android 2.3 to work with HLS out of the box, but I did find that using the Vitamio library worked pretty well (see this question for further info)

Community
  • 1
  • 1
HaemEternal
  • 2,229
  • 6
  • 31
  • 50
  • 1
    Did you find it necessary to recode MP4's with handbrake before transmuxing and segmenting with mediafilesegmenter? I tried a 360p MP4 from youtube (h.264 with aac) and processed with mediafilesegmenter; the resulting HLS plays fine on iPad, but hangs after 1 sec on Android 4.0.3. – Fixee Jul 03 '13 at 05:57
  • 1
    @Fixee Yes, I found that the setup of the MP4 was probably more important than the settings used for segmentation. As mentioned above, I found that audio settings were more likely to screw it up than video. As a test, try adding the -A flag in mediafilesegmenter. That will give you a video without audio. If that streams correctly, you'll know that it's the audio setup you need to tweak. – HaemEternal Jul 03 '13 at 09:27
  • 1
    Using -A clears up all problems with video display I was having. Thanks.. time to go muck around with audio settings now! :) – Fixee Jul 03 '13 at 23:26
  • Moved from Flash Media Server vod (used ext-x-version 2 which did not support floating point values) to making our own .ts files, hosting, and serving them elsewhere albeit with ext-x-version 3 and floating point durations. Android broke. Changing just the `#EXTINF:` lines to integer values seems to have fixed it. – notacouch Feb 17 '14 at 01:48
3

Some versions of Android seem to interpret the HLS at http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8 as live HLS rather than VOD HLS, and thus media player starts close to the "live" point, close to the content end, around 29 minutes into the content.

And here's why: prior to 4.3, the last line in an HLS playlist file was not parsed unless it ended in '\n'.

See the history of changes on that file: http://androidxref.com/4.3_r2.1/history/frameworks/av/media/libstagefright/httplive/M3UParser.cpp , on 12/31/12, there is change that fixed the problem. The issue is gone on 4.4.

So, one way to solve the problem on older versions is to add newline after the last line of the playlist on the server, or implement an HTTP proxy in your app that effectively adds that newline, which may not be trivial...

Dino
  • 31
  • 2
1

Did you try to give the Player a start parameter in the URL?

Like this:

"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8?start=0"

BenjaminH
  • 11
  • 1
-1
   <?xml version="1.0" encoding="utf-8" ?> 
    - <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
      <VideoView android:id="@+id/surface_view" android:layout_width="fill_parent" android:layout_height="300dp" android:layout_gravity="center" /> 
      <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@+id/surface_view" android:layout_marginRight="62dp" android:layout_marginTop="16dp" android:text="Stop" /> 
      <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/button1" android:layout_alignBottom="@+id/button1" android:layout_alignParentLeft="true" android:layout_marginLeft="34dp" android:text="Start" /> 
      </RelativeLayout>

*******************************************************************
     startB.setOnClickListener(new View.OnClickListener() {
@Override
            public void onClick(View v) {
                 mVideoView = (VideoView) findViewById(R.id.surface_view);
                   mVideoView.setVideoURI(Uri.parse("http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"));                
                   mVideoView.setMediaController(new     MediaController(MainActivity.this));
                   mVideoView.requestFocus();              
                   mVideoView.postInvalidateDelayed(100);  
                  new Thread(new Runnable() {
                      public void run() {
                          mVideoView.start();

                      }
                  }).start();
            }
        });
PankajSharma
  • 1,529
  • 14
  • 27
  • Thanks for the response @Pankaj. Unfortunately, I still see the same issue. Your code works for me on ICS 4.0.4, but on Jellybean 4.2, the stream loads at 29 minutes 30 seconds – HaemEternal Jun 07 '13 at 07:22