Home | History | Annotate | Download | only in leanback
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 package com.example.android.leanback;
     15 
     16 import android.net.Uri;
     17 import android.os.Bundle;
     18 import android.support.v4.media.session.MediaSessionCompat;
     19 
     20 import androidx.leanback.app.VideoFragmentGlueHost;
     21 import androidx.leanback.media.MediaPlayerAdapter;
     22 import androidx.leanback.media.PlaybackGlue;
     23 import androidx.leanback.media.PlaybackTransportControlGlue;
     24 import androidx.leanback.widget.PlaybackControlsRow;
     25 
     26 /**
     27  * Fragment demonstrating the use of {@link androidx.leanback.app.VideoFragment} to
     28  * render video with playback controls. And demonstrates video seeking with thumbnails.
     29  *
     30  * Generate 1 frame per second thumbnail bitmaps and put on sdcard:
     31  * <pre>
     32  * sudo apt-get install libav-tools
     33  * avconv -i input.mp4 -s 240x135 -vsync 1 -r 1 -an -y -qscale 8 frame_%04d.jpg
     34  * adb shell mkdir /sdcard/seek
     35  * adb push frame_*.jpg /sdcard/seek/
     36  * </pre>
     37  * Change to 1 frame per minute: use "-r 1/60".
     38  * For more options, see https://wiki.libav.org/Snippets/avconv
     39  *
     40  * <p>
     41  * Showcase:
     42  * </p>
     43  * <li>Auto play when ready</li>
     44  * <li>Set seek provider</li>
     45  * <li>switch MediaSource</li>
     46  * <li>switch PlaybackGlue</li>
     47  */
     48 public class SampleVideoFragment extends androidx.leanback.app.VideoFragment {
     49 
     50     // Media Session Token
     51     private static final String MEDIA_SESSION_COMPAT_TOKEN = "media session support video";
     52 
     53     private PlaybackTransportControlGlueSample<MediaPlayerAdapter> mMediaPlayerGlue;
     54 
     55     private MediaSessionCompat mMediaSessionCompat;
     56 
     57     final VideoFragmentGlueHost mHost = new VideoFragmentGlueHost(SampleVideoFragment.this);
     58 
     59     static void playWhenReady(PlaybackGlue glue) {
     60         if (glue.isPrepared()) {
     61             glue.play();
     62         } else {
     63             glue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
     64                 @Override
     65                 public void onPreparedStateChanged(PlaybackGlue glue) {
     66                     if (glue.isPrepared()) {
     67                         glue.removePlayerCallback(this);
     68                         glue.play();
     69                     }
     70                 }
     71             });
     72         }
     73     }
     74 
     75     static void loadSeekData(final PlaybackTransportControlGlue glue) {
     76         if (glue.isPrepared()) {
     77             glue.setSeekProvider(new PlaybackSeekDiskDataProvider(
     78                     glue.getDuration(),
     79                     1000,
     80                     "/sdcard/seek/frame_%04d.jpg"));
     81         } else {
     82             glue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
     83                 @Override
     84                 public void onPreparedStateChanged(PlaybackGlue glue) {
     85                     if (glue.isPrepared()) {
     86                         glue.removePlayerCallback(this);
     87                         PlaybackTransportControlGlue transportControlGlue =
     88                                 (PlaybackTransportControlGlue) glue;
     89                         transportControlGlue.setSeekProvider(new PlaybackSeekDiskDataProvider(
     90                                 transportControlGlue.getDuration(),
     91                                 1000,
     92                                 "/sdcard/seek/frame_%04d.jpg"));
     93                     }
     94                 }
     95             });
     96         }
     97     }
     98 
     99     @Override
    100     public void onCreate(Bundle savedInstanceState) {
    101         super.onCreate(savedInstanceState);
    102         mMediaPlayerGlue = new PlaybackTransportControlGlueSample(getActivity(),
    103                 new MediaPlayerAdapter(getActivity()));
    104 
    105         // create a media session inside of a fragment, and app developer can determine if connect
    106         // this media session to glue or not
    107         // as requested in b/64935838
    108         mMediaSessionCompat = new MediaSessionCompat(getActivity(), MEDIA_SESSION_COMPAT_TOKEN);
    109         mMediaPlayerGlue.connectToMediaSession(mMediaSessionCompat);
    110 
    111         mMediaPlayerGlue.setHost(mHost);
    112         mMediaPlayerGlue.setMode(PlaybackControlsRow.RepeatAction.INDEX_NONE);
    113         mMediaPlayerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
    114             boolean mSecondCompleted = false;
    115             @Override
    116             public void onPlayCompleted(PlaybackGlue glue) {
    117                 if (!mSecondCompleted) {
    118                     mSecondCompleted = true;
    119                     mMediaPlayerGlue.setSubtitle("Leanback artist Changed!");
    120                     mMediaPlayerGlue.setTitle("Leanback team at work");
    121                     String uriPath = "https://storage.googleapis.com/android-tv/Sample videos/"
    122                             + "April Fool's 2013/Explore Treasure Mode with Google Maps.mp4";
    123                     mMediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath));
    124                     loadSeekData(mMediaPlayerGlue);
    125                     playWhenReady(mMediaPlayerGlue);
    126                 } else {
    127                     mMediaPlayerGlue.removePlayerCallback(this);
    128                     switchAnotherGlue();
    129                 }
    130             }
    131         });
    132         mMediaPlayerGlue.setSubtitle("Leanback artist");
    133         mMediaPlayerGlue.setTitle("Leanback team at work");
    134         String uriPath = "https://storage.googleapis.com/android-tv/Sample videos/"
    135                 + "April Fool's 2013/Explore Treasure Mode with Google Maps.mp4";
    136         mMediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath));
    137         loadSeekData(mMediaPlayerGlue);
    138         playWhenReady(mMediaPlayerGlue);
    139     }
    140 
    141     @Override
    142     public void onPause() {
    143         if (mMediaPlayerGlue != null) {
    144             mMediaPlayerGlue.pause();
    145         }
    146         super.onPause();
    147     }
    148 
    149     @Override
    150     public void onDestroy() {
    151         super.onDestroy();
    152         mMediaPlayerGlue.disconnectToMediaSession();
    153     }
    154 
    155     void switchAnotherGlue() {
    156         mMediaPlayerGlue = new PlaybackTransportControlGlueSample(getActivity(),
    157                 new MediaPlayerAdapter(getActivity()));
    158 
    159         // If the glue is switched, re-register the media session
    160         mMediaPlayerGlue.connectToMediaSession(mMediaSessionCompat);
    161 
    162         mMediaPlayerGlue.setMode(PlaybackControlsRow.RepeatAction.INDEX_ONE);
    163         mMediaPlayerGlue.setSubtitle("A Googler");
    164         mMediaPlayerGlue.setTitle("Swimming with the fishes");
    165         mMediaPlayerGlue.getPlayerAdapter().setDataSource(
    166                 Uri.parse("http://techslides.com/demos/sample-videos/small.mp4"));
    167         mMediaPlayerGlue.setHost(mHost);
    168         loadSeekData(mMediaPlayerGlue);
    169         playWhenReady(mMediaPlayerGlue);
    170     }
    171 }
    172