Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.media.remote; | 5 package org.chromium.chrome.browser.media.remote; |
| 6 | 6 |
| 7 import android.app.PendingIntent; | 7 import android.app.PendingIntent; |
| 8 import android.content.BroadcastReceiver; | 8 import android.content.BroadcastReceiver; |
| 9 import android.content.Context; | 9 import android.content.Context; |
| 10 import android.content.Intent; | 10 import android.content.Intent; |
| 11 import android.content.IntentFilter; | 11 import android.content.IntentFilter; |
| 12 import android.net.Uri; | 12 import android.net.Uri; |
| 13 import android.os.Bundle; | 13 import android.os.Bundle; |
| 14 import android.os.SystemClock; | 14 import android.os.SystemClock; |
| 15 import android.support.v7.media.MediaControlIntent; | 15 import android.support.v7.media.MediaControlIntent; |
| 16 import android.support.v7.media.MediaItemMetadata; | 16 import android.support.v7.media.MediaItemMetadata; |
| 17 import android.support.v7.media.MediaItemStatus; | 17 import android.support.v7.media.MediaItemStatus; |
| 18 import android.support.v7.media.MediaRouteSelector; | 18 import android.support.v7.media.MediaRouteSelector; |
| 19 import android.support.v7.media.MediaRouter; | 19 import android.support.v7.media.MediaRouter; |
| 20 import android.support.v7.media.MediaRouter.RouteInfo; | 20 import android.support.v7.media.MediaRouter.RouteInfo; |
| 21 import android.support.v7.media.MediaSessionStatus; | 21 import android.support.v7.media.MediaSessionStatus; |
| 22 import android.util.Log; | 22 import android.util.Log; |
| 23 import android.widget.Toast; | 23 import android.widget.Toast; |
| 24 | 24 |
| 25 import com.google.android.gms.cast.CastMediaControlIntent; | 25 import com.google.android.gms.cast.CastMediaControlIntent; |
| 26 | 26 |
| 27 import org.apache.http.Header; | |
| 28 import org.chromium.base.ApplicationState; | 27 import org.chromium.base.ApplicationState; |
| 29 import org.chromium.base.ApplicationStatus; | 28 import org.chromium.base.ApplicationStatus; |
| 30 import org.chromium.base.CommandLine; | 29 import org.chromium.base.CommandLine; |
| 31 import org.chromium.chrome.ChromeSwitches; | 30 import org.chromium.chrome.ChromeSwitches; |
| 32 import org.chromium.chrome.R; | 31 import org.chromium.chrome.R; |
| 33 import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState; | 32 import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState; |
| 34 | 33 |
| 35 import java.net.URI; | 34 import java.net.URI; |
| 36 import java.net.URISyntaxException; | 35 import java.net.URISyntaxException; |
| 36 import java.util.List; | |
| 37 import java.util.Map; | |
| 37 | 38 |
| 38 import javax.annotation.Nullable; | 39 import javax.annotation.Nullable; |
| 39 | 40 |
| 40 /** | 41 /** |
| 41 * Class that abstracts all communication to and from the Android MediaRoutes. T his class is | 42 * Class that abstracts all communication to and from the Android MediaRoutes. T his class is |
| 42 * responsible for connecting to the MRs as well as sending commands and receivi ng status updates | 43 * responsible for connecting to the MRs as well as sending commands and receivi ng status updates |
| 43 * from the remote player. | 44 * from the remote player. |
| 44 * | 45 * |
| 45 * We have three main scenarios for Cast: | 46 * We have three main scenarios for Cast: |
| 46 * | 47 * |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 void onError(String message, Bundle data); | 87 void onError(String message, Bundle data); |
| 87 } | 88 } |
| 88 | 89 |
| 89 private static final String TAG = "DefaultMediaRouteController"; | 90 private static final String TAG = "DefaultMediaRouteController"; |
| 90 | 91 |
| 91 private static final String ACTION_RECEIVE_SESSION_STATUS_UPDATE = | 92 private static final String ACTION_RECEIVE_SESSION_STATUS_UPDATE = |
| 92 "com.google.android.apps.chrome.videofling.RECEIVE_SESSION_STATUS_UP DATE"; | 93 "com.google.android.apps.chrome.videofling.RECEIVE_SESSION_STATUS_UP DATE"; |
| 93 private static final String ACTION_RECEIVE_MEDIA_STATUS_UPDATE = | 94 private static final String ACTION_RECEIVE_MEDIA_STATUS_UPDATE = |
| 94 "com.google.android.apps.chrome.videofling.RECEIVE_MEDIA_STATUS_UPDA TE"; | 95 "com.google.android.apps.chrome.videofling.RECEIVE_MEDIA_STATUS_UPDA TE"; |
| 95 private static final String MIME_TYPE = "video/mp4"; | 96 private static final String MIME_TYPE = "video/mp4"; |
| 97 private static final String CORS_HEADER_NAME = "Access-Control-Allow-Origin" ; | |
| 96 | 98 |
| 97 private boolean mDebug; | 99 private boolean mDebug; |
| 98 private String mCurrentSessionId; | 100 private String mCurrentSessionId; |
| 99 private String mCurrentItemId; | 101 private String mCurrentItemId; |
| 100 private int mStreamPositionTimestamp; | 102 private int mStreamPositionTimestamp; |
| 101 private int mLastKnownStreamPosition; | 103 private int mLastKnownStreamPosition; |
| 102 private int mStreamDuration; | 104 private int mStreamDuration; |
| 103 private boolean mSeeking; | 105 private boolean mSeeking; |
| 104 private final String mIntentCategory; | 106 private final String mIntentCategory; |
| 105 private PendingIntent mSessionStatusUpdateIntent; | 107 private PendingIntent mSessionStatusUpdateIntent; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 public Uri getUri() { | 151 public Uri getUri() { |
| 150 return mLocalVideoUri; | 152 return mLocalVideoUri; |
| 151 } | 153 } |
| 152 | 154 |
| 153 @Override | 155 @Override |
| 154 public String getCookies() { | 156 public String getCookies() { |
| 155 return mLocalVideoCookies; | 157 return mLocalVideoCookies; |
| 156 } | 158 } |
| 157 | 159 |
| 158 @Override | 160 @Override |
| 159 public void setUri(Uri uri, Header[] headers) { | 161 public void setUri(Uri uri, Map<String, List<String>> headers) { |
| 160 if (canPlayMedia(uri, headers)) { | 162 if (canPlayMedia(uri, headers)) { |
| 161 mLocalVideoUri = uri; | 163 mLocalVideoUri = uri; |
| 162 playMedia(); | 164 playMedia(); |
| 163 return; | 165 return; |
| 164 } | 166 } |
| 165 mLocalVideoUri = null; | 167 mLocalVideoUri = null; |
| 166 showMessageToast( | 168 showMessageToast( |
| 167 getContext().getString(R.string.cast_permission_erro r_playing_video)); | 169 getContext().getString(R.string.cast_permission_erro r_playing_video)); |
| 168 release(); | 170 release(); |
| 169 } | 171 } |
| (...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1040 if (mMediaUrlResolver != null) mMediaUrlResolver.cancel(true); | 1042 if (mMediaUrlResolver != null) mMediaUrlResolver.cancel(true); |
| 1041 | 1043 |
| 1042 // Create a new MediaUrlResolver since the previous one may still be run ning despite the | 1044 // Create a new MediaUrlResolver since the previous one may still be run ning despite the |
| 1043 // cancel() call. | 1045 // cancel() call. |
| 1044 mMediaUrlResolver = new MediaUrlResolver(getContext(), mMediaUrlResolver Delegate); | 1046 mMediaUrlResolver = new MediaUrlResolver(getContext(), mMediaUrlResolver Delegate); |
| 1045 | 1047 |
| 1046 mStartPositionMillis = startPositionMillis; | 1048 mStartPositionMillis = startPositionMillis; |
| 1047 mMediaUrlResolver.execute(); | 1049 mMediaUrlResolver.execute(); |
| 1048 } | 1050 } |
| 1049 | 1051 |
| 1050 private boolean canPlayMedia(Uri uri, Header[] headers) { | 1052 private boolean canPlayMedia(Uri uri, Map<String, List<String>> headers) { |
|
whywhat
2015/03/30 15:51:34
As I explain in the other comment I'd rather move
aberent
2015/03/30 17:24:04
Done.
| |
| 1051 if (uri == Uri.EMPTY) return false; | 1053 if (uri == Uri.EMPTY) return false; |
| 1052 | 1054 |
| 1053 // HLS media requires Cors headers. Since these are the only ones | 1055 // HLS media requires Cors headers. Since these are the only ones |
| 1054 // sent now we can just check that headers is not empty but | 1056 // sent now we can just check that headers is not empty but |
| 1055 // if more headers are added we should be more strict in the check. | 1057 // if more headers are added we should be more strict in the check. |
| 1056 if ((headers == null || headers.length == 0) && isEnhancedMedia(uri)) { | 1058 if ((headers == null || !headers.containsKey(CORS_HEADER_NAME)) && isEnh ancedMedia(uri)) { |
| 1057 if (mDebug) Log.d(TAG, "HLS stream without CORs header: " + uri); | 1059 if (mDebug) Log.d(TAG, "HLS stream without CORs header: " + uri); |
| 1058 return false; | 1060 return false; |
| 1059 } | 1061 } |
| 1060 return true; | 1062 return true; |
| 1061 } | 1063 } |
| 1062 | 1064 |
| 1063 private void playMedia() { | 1065 private void playMedia() { |
| 1064 String title = getMediaStateListener().getTitle(); | 1066 String title = getMediaStateListener().getTitle(); |
| 1065 playUri(mLocalVideoUri, title, mStartPositionMillis); | 1067 playUri(mLocalVideoUri, title, mStartPositionMillis); |
| 1066 } | 1068 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1092 return SMOOTHSTREAM_MEDIA; | 1094 return SMOOTHSTREAM_MEDIA; |
| 1093 } | 1095 } |
| 1094 return UNKNOWN_MEDIA; | 1096 return UNKNOWN_MEDIA; |
| 1095 } | 1097 } |
| 1096 | 1098 |
| 1097 private boolean isEnhancedMedia(Uri videoUri) { | 1099 private boolean isEnhancedMedia(Uri videoUri) { |
| 1098 int mediaType = getMediaType(videoUri); | 1100 int mediaType = getMediaType(videoUri); |
| 1099 return mediaType == HLS_MEDIA || mediaType == DASH_MEDIA || mediaType == SMOOTHSTREAM_MEDIA; | 1101 return mediaType == HLS_MEDIA || mediaType == DASH_MEDIA || mediaType == SMOOTHSTREAM_MEDIA; |
| 1100 } | 1102 } |
| 1101 } | 1103 } |
| OLD | NEW |