Home | History | Annotate | Download | only in libaah_rtp
      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