1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "LibAAH_RTP" 18 //#define LOG_NDEBUG 0 19 20 #include <binder/IServiceManager.h> 21 #include <media/MediaPlayerInterface.h> 22 #include <utils/Log.h> 23 24 #include "aah_rx_player.h" 25 26 namespace android { 27 28 const uint32_t AAH_RXPlayer::kRTPRingBufferSize = 1 << 10; 29 30 sp<MediaPlayerBase> createAAH_RXPlayer() { 31 sp<MediaPlayerBase> ret = new AAH_RXPlayer(); 32 return ret; 33 } 34 35 AAH_RXPlayer::AAH_RXPlayer() 36 : ring_buffer_(kRTPRingBufferSize) 37 , substreams_(NULL) { 38 thread_wrapper_ = new ThreadWrapper(*this); 39 40 is_playing_ = false; 41 multicast_joined_ = false; 42 transmitter_known_ = false; 43 current_epoch_known_ = false; 44 data_source_set_ = false; 45 sock_fd_ = -1; 46 47 substreams_.setCapacity(4); 48 49 memset(&listen_addr_, 0, sizeof(listen_addr_)); 50 memset(&transmitter_addr_, 0, sizeof(transmitter_addr_)); 51 52 fetchAudioFlinger(); 53 } 54 55 AAH_RXPlayer::~AAH_RXPlayer() { 56 reset_l(); 57 CHECK(substreams_.size() == 0); 58 omx_.disconnect(); 59 } 60 61 status_t AAH_RXPlayer::initCheck() { 62 if (thread_wrapper_ == NULL) { 63 ALOGE("Failed to allocate thread wrapper!"); 64 return NO_MEMORY; 65 } 66 67 if (!ring_buffer_.initCheck()) { 68 ALOGE("Failed to allocate reassembly ring buffer!"); 69 return NO_MEMORY; 70 } 71 72 // Check for the presense of the common time service by attempting to query 73 // for CommonTime's frequency. If we get an error back, we cannot talk to 74 // the service at all and should abort now. 75 status_t res; 76 uint64_t freq; 77 res = cc_helper_.getCommonFreq(&freq); 78 if (OK != res) { 79 ALOGE("Failed to connect to common time service!"); 80 return res; 81 } 82 83 return omx_.connect(); 84 } 85 86 status_t AAH_RXPlayer::setDataSource( 87 const char *url, 88 const KeyedVector<String8, String8> *headers) { 89 AutoMutex api_lock(&api_lock_); 90 uint32_t a, b, c, d; 91 uint16_t port; 92 93 if (data_source_set_) { 94 return INVALID_OPERATION; 95 } 96 97 if (NULL == url) { 98 return BAD_VALUE; 99 } 100 101 if (5 != sscanf(url, "%*[^:/]://%u.%u.%u.%u:%hu", &a, &b, &c, &d, &port)) { 102 ALOGE("Failed to parse URL \"%s\"", url); 103 return BAD_VALUE; 104 } 105 106 if ((a > 255) || (b > 255) || (c > 255) || (d > 255) || (port == 0)) { 107 ALOGE("Bad multicast address \"%s\"", url); 108 return BAD_VALUE; 109 } 110 111 ALOGI("setDataSource :: %u.%u.%u.%u:%hu", a, b, c, d, port); 112 113 a = (a << 24) | (b << 16) | (c << 8) | d; 114 115 memset(&listen_addr_, 0, sizeof(listen_addr_)); 116 listen_addr_.sin_family = AF_INET; 117 listen_addr_.sin_port = htons(port); 118 listen_addr_.sin_addr.s_addr = htonl(a); 119 data_source_set_ = true; 120 121 return OK; 122 } 123 124 status_t AAH_RXPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 125 return INVALID_OPERATION; 126 } 127 128 status_t AAH_RXPlayer::setVideoSurface(const sp<Surface>& surface) { 129 return OK; 130 } 131 132 status_t AAH_RXPlayer::setVideoSurfaceTexture( 133 const sp<ISurfaceTexture>& surfaceTexture) { 134 return OK; 135 } 136 137 status_t AAH_RXPlayer::prepare() { 138 return OK; 139 } 140 141 status_t AAH_RXPlayer::prepareAsync() { 142 sendEvent(MEDIA_PREPARED); 143 return OK; 144 } 145 146 status_t AAH_RXPlayer::start() { 147 AutoMutex api_lock(&api_lock_); 148 149 if (is_playing_) { 150 return OK; 151 } 152 153 status_t res = startWorkThread(); 154 is_playing_ = (res == OK); 155 return res; 156 } 157 158 status_t AAH_RXPlayer::stop() { 159 return pause(); 160 } 161 162 status_t AAH_RXPlayer::pause() { 163 AutoMutex api_lock(&api_lock_); 164 stopWorkThread(); 165 CHECK(sock_fd_ < 0); 166 is_playing_ = false; 167 return OK; 168 } 169 170 bool AAH_RXPlayer::isPlaying() { 171 AutoMutex api_lock(&api_lock_); 172 return is_playing_; 173 } 174 175 status_t AAH_RXPlayer::seekTo(int msec) { 176 sendEvent(MEDIA_SEEK_COMPLETE); 177 return OK; 178 } 179 180 status_t AAH_RXPlayer::getCurrentPosition(int *msec) { 181 if (NULL != msec) { 182 *msec = 0; 183 } 184 return OK; 185 } 186 187 status_t AAH_RXPlayer::getDuration(int *msec) { 188 if (NULL != msec) { 189 *msec = 1; 190 } 191 return OK; 192 } 193 194 status_t AAH_RXPlayer::reset() { 195 AutoMutex api_lock(&api_lock_); 196 reset_l(); 197 return OK; 198 } 199 200 void AAH_RXPlayer::reset_l() { 201 stopWorkThread(); 202 CHECK(sock_fd_ < 0); 203 CHECK(!multicast_joined_); 204 is_playing_ = false; 205 data_source_set_ = false; 206 transmitter_known_ = false; 207 memset(&listen_addr_, 0, sizeof(listen_addr_)); 208 } 209 210 status_t AAH_RXPlayer::setLooping(int loop) { 211 return OK; 212 } 213 214 player_type AAH_RXPlayer::playerType() { 215 return AAH_RX_PLAYER; 216 } 217 218 status_t AAH_RXPlayer::setParameter(int key, const Parcel &request) { 219 return ERROR_UNSUPPORTED; 220 } 221 222 status_t AAH_RXPlayer::getParameter(int key, Parcel *reply) { 223 return ERROR_UNSUPPORTED; 224 } 225 226 status_t AAH_RXPlayer::invoke(const Parcel& request, Parcel *reply) { 227 if (!reply) { 228 return BAD_VALUE; 229 } 230 231 int32_t magic; 232 status_t err = request.readInt32(&magic); 233 if (err != OK) { 234 reply->writeInt32(err); 235 return OK; 236 } 237 238 if (magic != 0x12345) { 239 reply->writeInt32(BAD_VALUE); 240 return OK; 241 } 242 243 int32_t methodID; 244 err = request.readInt32(&methodID); 245 if (err != OK) { 246 reply->writeInt32(err); 247 return OK; 248 } 249 250 switch (methodID) { 251 // Get Volume 252 case INVOKE_GET_MASTER_VOLUME: { 253 if (audio_flinger_ != NULL) { 254 reply->writeInt32(OK); 255 reply->writeFloat(audio_flinger_->masterVolume()); 256 } else { 257 reply->writeInt32(UNKNOWN_ERROR); 258 } 259 } break; 260 261 // Set Volume 262 case INVOKE_SET_MASTER_VOLUME: { 263 float targetVol = request.readFloat(); 264 reply->writeInt32(audio_flinger_->setMasterVolume(targetVol)); 265 } break; 266 267 default: return BAD_VALUE; 268 } 269 270 return OK; 271 } 272 273 void AAH_RXPlayer::fetchAudioFlinger() { 274 if (audio_flinger_ == NULL) { 275 sp<IServiceManager> sm = defaultServiceManager(); 276 sp<IBinder> binder; 277 binder = sm->getService(String16("media.audio_flinger")); 278 279 if (binder == NULL) { 280 ALOGW("AAH_RXPlayer failed to fetch handle to audio flinger." 281 " Master volume control will not be possible."); 282 } 283 284 audio_flinger_ = interface_cast<IAudioFlinger>(binder); 285 } 286 } 287 288 } // namespace android 289