1*30877f79SAndroid Build Coastguard Worker---
2*30877f79SAndroid Build Coastguard Workertitle: Media items
3*30877f79SAndroid Build Coastguard Worker---
4*30877f79SAndroid Build Coastguard Worker
5*30877f79SAndroid Build Coastguard WorkerThe [playlist API][] is based on `MediaItem`s, which can be conveniently built
6*30877f79SAndroid Build Coastguard Workerusing `MediaItem.Builder`. Inside the player, media items are converted into
7*30877f79SAndroid Build Coastguard Workerplayable `MediaSource`s by a `MediaSource.Factory`. Without
8*30877f79SAndroid Build Coastguard Worker[custom configuration]({{ site.baseurl }}/media-sources.html#customizing-media-source-creation),
9*30877f79SAndroid Build Coastguard Workerthis conversion is carried out by a `DefaultMediaSourceFactory`, which is
10*30877f79SAndroid Build Coastguard Workercapable of building complex media sources corresponding to the properties of the
11*30877f79SAndroid Build Coastguard Workermedia item. Some of the properties that can be set on media items are outlined
12*30877f79SAndroid Build Coastguard Workerbelow.
13*30877f79SAndroid Build Coastguard Worker
14*30877f79SAndroid Build Coastguard Worker## Simple media items ##
15*30877f79SAndroid Build Coastguard Worker
16*30877f79SAndroid Build Coastguard WorkerA media item consisting only of the stream URI can be built with the `fromUri`
17*30877f79SAndroid Build Coastguard Workerconvenience method:
18*30877f79SAndroid Build Coastguard Worker
19*30877f79SAndroid Build Coastguard Worker~~~
20*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem = MediaItem.fromUri(videoUri);
21*30877f79SAndroid Build Coastguard Worker~~~
22*30877f79SAndroid Build Coastguard Worker{: .language-java}
23*30877f79SAndroid Build Coastguard Worker
24*30877f79SAndroid Build Coastguard WorkerFor all other cases a `MediaItem.Builder` can be used. In the example below, a
25*30877f79SAndroid Build Coastguard Workermedia item is built with an ID and some attached metadata:
26*30877f79SAndroid Build Coastguard Worker
27*30877f79SAndroid Build Coastguard Worker~~~
28*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem = new MediaItem.Builder()
29*30877f79SAndroid Build Coastguard Worker    .setUri(videoUri)
30*30877f79SAndroid Build Coastguard Worker    .setMediaId(mediaId)
31*30877f79SAndroid Build Coastguard Worker    .setTag(metadata)
32*30877f79SAndroid Build Coastguard Worker    .build();
33*30877f79SAndroid Build Coastguard Worker~~~
34*30877f79SAndroid Build Coastguard Worker{: .language-java}
35*30877f79SAndroid Build Coastguard Worker
36*30877f79SAndroid Build Coastguard WorkerAttaching metadata can be useful for
37*30877f79SAndroid Build Coastguard Worker[updating your app's UI]({{ site.baseurl }}/playlists.html#detecting-when-playback-transitions-to-another-media-item)
38*30877f79SAndroid Build Coastguard Workerwhen playlist transitions occur.
39*30877f79SAndroid Build Coastguard Worker
40*30877f79SAndroid Build Coastguard Worker## Handling non-standard file extensions
41*30877f79SAndroid Build Coastguard Worker
42*30877f79SAndroid Build Coastguard WorkerThe ExoPlayer library provides adaptive media sources for DASH, HLS and
43*30877f79SAndroid Build Coastguard WorkerSmoothStreaming. If the URI of such an adaptive media item ends with a standard
44*30877f79SAndroid Build Coastguard Workerfile extension, the corresponding media source is automatically created. If the
45*30877f79SAndroid Build Coastguard WorkerURI has a non-standard extension or no extension at all, then the MIME type can
46*30877f79SAndroid Build Coastguard Workerbe set explicitly to indicate the type of the media item:
47*30877f79SAndroid Build Coastguard Worker
48*30877f79SAndroid Build Coastguard Worker~~~
49*30877f79SAndroid Build Coastguard Worker// Use the explicit MIME type to build an HLS media item.
50*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem = new MediaItem.Builder()
51*30877f79SAndroid Build Coastguard Worker    .setUri(hlsUri)
52*30877f79SAndroid Build Coastguard Worker    .setMimeType(MimeTypes.APPLICATION_M3U8)
53*30877f79SAndroid Build Coastguard Worker    .build();
54*30877f79SAndroid Build Coastguard Worker~~~
55*30877f79SAndroid Build Coastguard Worker{: .language-java}
56*30877f79SAndroid Build Coastguard Worker
57*30877f79SAndroid Build Coastguard WorkerFor progressive media streams a MIME type is not required.
58*30877f79SAndroid Build Coastguard Worker
59*30877f79SAndroid Build Coastguard Worker## Protected content ##
60*30877f79SAndroid Build Coastguard Worker
61*30877f79SAndroid Build Coastguard WorkerFor protected content, the media item's DRM properties should be set:
62*30877f79SAndroid Build Coastguard Worker
63*30877f79SAndroid Build Coastguard Worker~~~
64*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem = new MediaItem.Builder()
65*30877f79SAndroid Build Coastguard Worker    .setUri(videoUri)
66*30877f79SAndroid Build Coastguard Worker    .setDrmConfiguration(
67*30877f79SAndroid Build Coastguard Worker        new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
68*30877f79SAndroid Build Coastguard Worker            .setLicenseUri(licenseUri)
69*30877f79SAndroid Build Coastguard Worker            .setMultiSession(true)
70*30877f79SAndroid Build Coastguard Worker            .setLicenseRequestHeaders(httpRequestHeaders)
71*30877f79SAndroid Build Coastguard Worker            .build())
72*30877f79SAndroid Build Coastguard Worker    .build();
73*30877f79SAndroid Build Coastguard Worker~~~
74*30877f79SAndroid Build Coastguard Worker{: .language-java}
75*30877f79SAndroid Build Coastguard Worker
76*30877f79SAndroid Build Coastguard WorkerThis example builds a media item for Widevine protected content. Inside the
77*30877f79SAndroid Build Coastguard Workerplayer, `DefaultMediaSourceFactory` will pass these properties to a
78*30877f79SAndroid Build Coastguard Worker`DrmSessionManagerProvider` to obtain a `DrmSessionManager`, which is then
79*30877f79SAndroid Build Coastguard Workerinjected into the created `MediaSource`. DRM behaviour can be
80*30877f79SAndroid Build Coastguard Worker[further customized]({{ site.baseurl }}/drm.html#using-a-custom-drmsessionmanager)
81*30877f79SAndroid Build Coastguard Workerto your needs.
82*30877f79SAndroid Build Coastguard Worker
83*30877f79SAndroid Build Coastguard Worker## Sideloading subtitle tracks ##
84*30877f79SAndroid Build Coastguard Worker
85*30877f79SAndroid Build Coastguard WorkerTo sideload subtitle tracks, `MediaItem.Subtitle` instances can be added when
86*30877f79SAndroid Build Coastguard Workerwhen building a media item:
87*30877f79SAndroid Build Coastguard Worker
88*30877f79SAndroid Build Coastguard Worker~~~
89*30877f79SAndroid Build Coastguard WorkerMediaItem.SubtitleConfiguration subtitle =
90*30877f79SAndroid Build Coastguard Worker    new MediaItem.SubtitleConfiguration.Builder(subtitleUri)
91*30877f79SAndroid Build Coastguard Worker        .setMimeType(MimeTypes.APPLICATION_SUBRIP) // The correct MIME type (required).
92*30877f79SAndroid Build Coastguard Worker        .setLanguage(language) // The subtitle language (optional).
93*30877f79SAndroid Build Coastguard Worker        .setSelectionFlags(selectionFlags) // Selection flags for the track (optional).
94*30877f79SAndroid Build Coastguard Worker        .build();
95*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem =
96*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
97*30877f79SAndroid Build Coastguard Worker        .setUri(videoUri)
98*30877f79SAndroid Build Coastguard Worker        .setSubtitleConfigurations(ImmutableList.of(subtitle))
99*30877f79SAndroid Build Coastguard Worker        .build();
100*30877f79SAndroid Build Coastguard Worker~~~
101*30877f79SAndroid Build Coastguard Worker{: .language-java}
102*30877f79SAndroid Build Coastguard Worker
103*30877f79SAndroid Build Coastguard WorkerInternally, `DefaultMediaSourceFactory` will use a `MergingMediaSource` to
104*30877f79SAndroid Build Coastguard Workercombine the content media source with a `SingleSampleMediaSource` for each
105*30877f79SAndroid Build Coastguard Workersubtitle track.
106*30877f79SAndroid Build Coastguard Worker
107*30877f79SAndroid Build Coastguard Worker## Clipping a media stream ##
108*30877f79SAndroid Build Coastguard Worker
109*30877f79SAndroid Build Coastguard WorkerIt's possible to clip the content referred to by a media item by setting custom
110*30877f79SAndroid Build Coastguard Workerstart and end positions:
111*30877f79SAndroid Build Coastguard Worker
112*30877f79SAndroid Build Coastguard Worker~~~
113*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem =
114*30877f79SAndroid Build Coastguard Worker    new MediaItem.Builder()
115*30877f79SAndroid Build Coastguard Worker        .setUri(videoUri)
116*30877f79SAndroid Build Coastguard Worker        .setClippingConfiguration(
117*30877f79SAndroid Build Coastguard Worker            new ClippingConfiguration.Builder()
118*30877f79SAndroid Build Coastguard Worker                .setStartPositionMs(startPositionMs)
119*30877f79SAndroid Build Coastguard Worker                .setEndPositionMs(endPositionMs)
120*30877f79SAndroid Build Coastguard Worker                .build())
121*30877f79SAndroid Build Coastguard Worker        .build();
122*30877f79SAndroid Build Coastguard Worker~~~
123*30877f79SAndroid Build Coastguard Worker{: .language-java}
124*30877f79SAndroid Build Coastguard Worker
125*30877f79SAndroid Build Coastguard WorkerInternally, `DefaultMediaSourceFactory` will use a `ClippingMediaSource` to wrap
126*30877f79SAndroid Build Coastguard Workerthe content media source. There are additional clipping properties. See the
127*30877f79SAndroid Build Coastguard Worker[`MediaItem.Builder` Javadoc][] for more details.
128*30877f79SAndroid Build Coastguard Worker
129*30877f79SAndroid Build Coastguard WorkerWhen clipping the start of a video file, try to align the start position with a
130*30877f79SAndroid Build Coastguard Workerkeyframe if possible. If the start position is not aligned with a keyframe then
131*30877f79SAndroid Build Coastguard Workerthe player will need to decode and discard data from the previous keyframe up to
132*30877f79SAndroid Build Coastguard Workerthe start position before playback can begin. This will introduce a short delay
133*30877f79SAndroid Build Coastguard Workerat the start of playback, including when the player transitions to playing a
134*30877f79SAndroid Build Coastguard Workerclipped media source as part of a playlist or due to looping.
135*30877f79SAndroid Build Coastguard Worker{:.info}
136*30877f79SAndroid Build Coastguard Worker
137*30877f79SAndroid Build Coastguard Worker## Ad insertion ##
138*30877f79SAndroid Build Coastguard Worker
139*30877f79SAndroid Build Coastguard WorkerTo insert ads, a media item's ad tag URI property should be set:
140*30877f79SAndroid Build Coastguard Worker
141*30877f79SAndroid Build Coastguard Worker~~~
142*30877f79SAndroid Build Coastguard WorkerMediaItem mediaItem = new MediaItem.Builder()
143*30877f79SAndroid Build Coastguard Worker    .setUri(videoUri)
144*30877f79SAndroid Build Coastguard Worker    .setAdsConfiguration(
145*30877f79SAndroid Build Coastguard Worker        new MediaItem.AdsConfiguration.Builder(adTagUri).build())
146*30877f79SAndroid Build Coastguard Worker    .build();
147*30877f79SAndroid Build Coastguard Worker~~~
148*30877f79SAndroid Build Coastguard Worker{: .language-java}
149*30877f79SAndroid Build Coastguard Worker
150*30877f79SAndroid Build Coastguard WorkerInternally, `DefaultMediaSourceFactory` will wrap the content media source in an
151*30877f79SAndroid Build Coastguard Worker`AdsMediaSource` to insert ads as defined by the ad tag. For this to work, the
152*30877f79SAndroid Build Coastguard Workerthe player also needs to have its `DefaultMediaSourceFactory`
153*30877f79SAndroid Build Coastguard Worker[configured accordingly]({{ site.baseurl }}/ad-insertion.html#declarative-ad-support).
154*30877f79SAndroid Build Coastguard Worker
155*30877f79SAndroid Build Coastguard Worker[playlist API]: {{ site.baseurl }}/playlists.html
156*30877f79SAndroid Build Coastguard Worker[`MediaItem.Builder` Javadoc]: {{ site.exo_sdk }}/MediaItem.Builder.html
157