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 */ 14package com.example.android.leanback; 15 16import android.net.Uri; 17import android.os.Bundle; 18import android.support.v17.leanback.app.VideoFragmentGlueHost; 19import android.support.v17.leanback.media.MediaPlayerAdapter; 20import android.support.v17.leanback.media.PlaybackGlue; 21import android.support.v17.leanback.media.PlaybackTransportControlGlue; 22import android.support.v17.leanback.widget.PlaybackControlsRow; 23 24/** 25 * Fragment demonstrating the use of {@link android.support.v17.leanback.app.VideoFragment} to 26 * render video with playback controls. And demonstrates video seeking with thumbnails. 27 * 28 * Generate 1 frame per second thumbnail bitmaps and put on sdcard: 29 * <pre> 30 * sudo apt-get install libav-tools 31 * avconv -i input.mp4 -s 240x135 -vsync 1 -r 1 -an -y -qscale 8 frame_%04d.jpg 32 * adb shell mkdir /sdcard/seek 33 * adb push frame_*.jpg /sdcard/seek/ 34 * </pre> 35 * Change to 1 frame per minute: use "-r 1/60". 36 * For more options, see https://wiki.libav.org/Snippets/avconv 37 * 38 * <p> 39 * Showcase: 40 * </p> 41 * <li>Auto play when ready</li> 42 * <li>Set seek provider</li> 43 * <li>switch MediaSource</li> 44 * <li>switch PlaybackGlue</li> 45 */ 46public class SampleVideoFragment extends android.support.v17.leanback.app.VideoFragment { 47 private PlaybackTransportControlGlueSample<MediaPlayerAdapter> mMediaPlayerGlue; 48 49 final VideoFragmentGlueHost mHost = new VideoFragmentGlueHost(SampleVideoFragment.this); 50 51 static void playWhenReady(PlaybackGlue glue) { 52 if (glue.isPrepared()) { 53 glue.play(); 54 } else { 55 glue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { 56 @Override 57 public void onPreparedStateChanged(PlaybackGlue glue) { 58 if (glue.isPrepared()) { 59 glue.removePlayerCallback(this); 60 glue.play(); 61 } 62 } 63 }); 64 } 65 } 66 67 static void loadSeekData(final PlaybackTransportControlGlue glue) { 68 if (glue.isPrepared()) { 69 glue.setSeekProvider(new PlaybackSeekDiskDataProvider( 70 glue.getDuration(), 71 1000, 72 "/sdcard/seek/frame_%04d.jpg")); 73 } else { 74 glue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { 75 @Override 76 public void onPreparedStateChanged(PlaybackGlue glue) { 77 if (glue.isPrepared()) { 78 glue.removePlayerCallback(this); 79 PlaybackTransportControlGlue transportControlGlue = 80 (PlaybackTransportControlGlue) glue; 81 transportControlGlue.setSeekProvider(new PlaybackSeekDiskDataProvider( 82 transportControlGlue.getDuration(), 83 1000, 84 "/sdcard/seek/frame_%04d.jpg")); 85 } 86 } 87 }); 88 } 89 } 90 91 @Override 92 public void onCreate(Bundle savedInstanceState) { 93 super.onCreate(savedInstanceState); 94 mMediaPlayerGlue = new PlaybackTransportControlGlueSample(getActivity(), 95 new MediaPlayerAdapter(getActivity())); 96 mMediaPlayerGlue.setHost(mHost); 97 mMediaPlayerGlue.setMode(PlaybackControlsRow.RepeatAction.INDEX_NONE); 98 mMediaPlayerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { 99 boolean mSecondCompleted = false; 100 @Override 101 public void onPlayCompleted(PlaybackGlue glue) { 102 if (!mSecondCompleted) { 103 mSecondCompleted = true; 104 mMediaPlayerGlue.setSubtitle("Leanback artist Changed!"); 105 mMediaPlayerGlue.setTitle("Leanback team at work"); 106 String uriPath = "https://storage.googleapis.com/android-tv/Sample videos/" 107 + "April Fool's 2013/Explore Treasure Mode with Google Maps.mp4"; 108 mMediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)); 109 loadSeekData(mMediaPlayerGlue); 110 playWhenReady(mMediaPlayerGlue); 111 } else { 112 mMediaPlayerGlue.removePlayerCallback(this); 113 switchAnotherGlue(); 114 } 115 } 116 }); 117 mMediaPlayerGlue.setSubtitle("Leanback artist"); 118 mMediaPlayerGlue.setTitle("Leanback team at work"); 119 String uriPath = "https://storage.googleapis.com/android-tv/Sample videos/" 120 + "April Fool's 2013/Explore Treasure Mode with Google Maps.mp4"; 121 mMediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)); 122 loadSeekData(mMediaPlayerGlue); 123 playWhenReady(mMediaPlayerGlue); 124 } 125 126 @Override 127 public void onPause() { 128 if (mMediaPlayerGlue != null) { 129 mMediaPlayerGlue.pause(); 130 } 131 super.onPause(); 132 } 133 134 void switchAnotherGlue() { 135 mMediaPlayerGlue = new PlaybackTransportControlGlueSample(getActivity(), 136 new MediaPlayerAdapter(getActivity())); 137 mMediaPlayerGlue.setMode(PlaybackControlsRow.RepeatAction.INDEX_ONE); 138 mMediaPlayerGlue.setSubtitle("A Googler"); 139 mMediaPlayerGlue.setTitle("Swimming with the fishes"); 140 mMediaPlayerGlue.getPlayerAdapter().setDataSource( 141 Uri.parse("http://techslides.com/demos/sample-videos/small.mp4")); 142 mMediaPlayerGlue.setHost(mHost); 143 loadSeekData(mMediaPlayerGlue); 144 playWhenReady(mMediaPlayerGlue); 145 } 146} 147