1aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata/*
2aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * Copyright (C) 2016 The Android Open Source Project
3aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata *
4aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * in compliance with the License. You may obtain a copy of the License at
6aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata *
7aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * http://www.apache.org/licenses/LICENSE-2.0
8aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata *
9aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * Unless required by applicable law or agreed to in writing, software distributed under the License
10aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * or implied. See the License for the specific language governing permissions and limitations under
12aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * the License.
13aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata */
14aa49439ba6276137f94fcdc1bf4f69b78833dad6susnatapackage com.example.android.leanback;
15aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
16aa49439ba6276137f94fcdc1bf4f69b78833dad6susnataimport android.net.Uri;
17aa49439ba6276137f94fcdc1bf4f69b78833dad6susnataimport android.os.Bundle;
18aa49439ba6276137f94fcdc1bf4f69b78833dad6susnataimport android.support.v17.leanback.app.VideoFragmentGlueHost;
193bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.media.MediaPlayerAdapter;
2095ac470f2bbea06114a64906d95c0da7d9412db0Dake Guimport android.support.v17.leanback.media.PlaybackGlue;
213bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.media.PlaybackTransportControlGlue;
223bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.widget.PlaybackControlsRow;
23aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
24aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata/**
25aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata * Fragment demonstrating the use of {@link android.support.v17.leanback.app.VideoFragment} to
26ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * render video with playback controls. And demonstrates video seeking with thumbnails.
27ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu *
28ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * Generate 1 frame per second thumbnail bitmaps and put on sdcard:
29ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * <pre>
30ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * sudo apt-get install libav-tools
31ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * avconv -i input.mp4 -s 240x135 -vsync 1 -r 1 -an -y -qscale 8 frame_%04d.jpg
32ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * adb shell mkdir /sdcard/seek
33ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * adb push frame_*.jpg /sdcard/seek/
34ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * </pre>
35ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * Change to 1 frame per minute: use "-r 1/60".
36ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu * For more options, see https://wiki.libav.org/Snippets/avconv
37ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu *
383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <p>
393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Showcase:
403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * </p>
413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>Auto play when ready</li>
423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>Set seek provider</li>
433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>switch MediaSource</li>
443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>switch PlaybackGlue</li>
45aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata */
46aa49439ba6276137f94fcdc1bf4f69b78833dad6susnatapublic class SampleVideoFragment extends android.support.v17.leanback.app.VideoFragment {
473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    private PlaybackTransportControlGlueSample<MediaPlayerAdapter> mMediaPlayerGlue;
48aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    final VideoFragmentGlueHost mHost = new VideoFragmentGlueHost(SampleVideoFragment.this);
50aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    static void playWhenReady(PlaybackGlue glue) {
523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (glue.isPrepared()) {
533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            glue.play();
543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        } else {
553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            glue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                @Override
573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                public void onPreparedStateChanged(PlaybackGlue glue) {
583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    if (glue.isPrepared()) {
593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                        glue.removePlayerCallback(this);
603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                        glue.play();
613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    }
623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                }
633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            });
643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
65aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata    }
66aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    static void loadSeekData(final PlaybackTransportControlGlue glue) {
683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (glue.isPrepared()) {
69ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu            glue.setSeekProvider(new PlaybackSeekDiskDataProvider(
703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    glue.getDuration(),
71ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu                    1000,
72ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu                    "/sdcard/seek/frame_%04d.jpg"));
733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        } else {
743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            glue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                @Override
763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                public void onPreparedStateChanged(PlaybackGlue glue) {
773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    if (glue.isPrepared()) {
783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                        glue.removePlayerCallback(this);
793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                        PlaybackTransportControlGlue transportControlGlue =
803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                                (PlaybackTransportControlGlue) glue;
81ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu                        transportControlGlue.setSeekProvider(new PlaybackSeekDiskDataProvider(
823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                                transportControlGlue.getDuration(),
83ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu                                1000,
84ffddec570a27891c0e13d24b1558c6f61ed99fb9Dake Gu                                "/sdcard/seek/frame_%04d.jpg"));
853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    }
863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                }
873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            });
883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
90aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
91aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata    @Override
923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void onCreate(Bundle savedInstanceState) {
933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        super.onCreate(savedInstanceState);
943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue = new PlaybackTransportControlGlueSample(getActivity(),
953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new MediaPlayerAdapter(getActivity()));
963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.setHost(mHost);
97946a01cfedb6838e98d7a37e30f64c39b603893dDake Gu        mMediaPlayerGlue.setMode(PlaybackControlsRow.RepeatAction.INDEX_NONE);
983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            boolean mSecondCompleted = false;
100aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata            @Override
1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void onPlayCompleted(PlaybackGlue glue) {
1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                if (!mSecondCompleted) {
1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mSecondCompleted = true;
1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mMediaPlayerGlue.setSubtitle("Leanback artist Changed!");
1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mMediaPlayerGlue.setTitle("Leanback team at work");
1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    String uriPath = "https://storage.googleapis.com/android-tv/Sample videos/"
1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                            + "April Fool's 2013/Explore Treasure Mode with Google Maps.mp4";
1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mMediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath));
1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    loadSeekData(mMediaPlayerGlue);
1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    playWhenReady(mMediaPlayerGlue);
1113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                } else {
1123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mMediaPlayerGlue.removePlayerCallback(this);
1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    switchAnotherGlue();
1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                }
115aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata            }
1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.setSubtitle("Leanback artist");
1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.setTitle("Leanback team at work");
1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        String uriPath = "https://storage.googleapis.com/android-tv/Sample videos/"
1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                + "April Fool's 2013/Explore Treasure Mode with Google Maps.mp4";
1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath));
1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        loadSeekData(mMediaPlayerGlue);
1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        playWhenReady(mMediaPlayerGlue);
1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
125aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Override
1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void onPause() {
1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mMediaPlayerGlue != null) {
1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            mMediaPlayerGlue.pause();
1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        super.onPause();
1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
133aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata
1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void switchAnotherGlue() {
1353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue = new PlaybackTransportControlGlueSample(getActivity(),
1363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new MediaPlayerAdapter(getActivity()));
137946a01cfedb6838e98d7a37e30f64c39b603893dDake Gu        mMediaPlayerGlue.setMode(PlaybackControlsRow.RepeatAction.INDEX_ONE);
1383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.setSubtitle("A Googler");
1393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.setTitle("Swimming with the fishes");
1403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.getPlayerAdapter().setDataSource(
1413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                Uri.parse("http://techslides.com/demos/sample-videos/small.mp4"));
1423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mMediaPlayerGlue.setHost(mHost);
1433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        loadSeekData(mMediaPlayerGlue);
1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        playWhenReady(mMediaPlayerGlue);
145aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata    }
146aa49439ba6276137f94fcdc1bf4f69b78833dad6susnata}
147