/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define USE_LOG SLAndroidLogLevel_Verbose

#include "sles_allinclusive.h"
#include "android_GenericMediaPlayer.h"

#include <media/IMediaPlayerService.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/mediaplayer.h>  // media_event_type media_error_type media_info_type

// default delay in Us used when reposting an event when the player is not ready to accept
// the command yet. This is for instance used when seeking on a MediaPlayer that's still preparing
#define DEFAULT_COMMAND_DELAY_FOR_REPOST_US (100*1000) // 100ms

// table of prefixes for known distant protocols; these are immediately dispatched to mediaserver
static const char* const kDistantProtocolPrefix[] = { "http://", "https://", "rtsp://"};
#define NB_DISTANT_PROTOCOLS (sizeof(kDistantProtocolPrefix)/sizeof(kDistantProtocolPrefix[0]))

// is the specified URI a known distant protocol?
bool isDistantProtocol(const char *uri)
{
    for (unsigned int i = 0; i < NB_DISTANT_PROTOCOLS; i++) {
        if (!strncasecmp(uri, kDistantProtocolPrefix[i], strlen(kDistantProtocolPrefix[i]))) {
            return true;
        }
    }
    return false;
}

namespace android {

//--------------------------------------------------------------------------------------------------
MediaPlayerNotificationClient::MediaPlayerNotificationClient(GenericMediaPlayer* gmp) :
    mGenericMediaPlayer(gmp),
    mPlayerPrepared(PREPARE_NOT_STARTED)
{
    SL_LOGV("MediaPlayerNotificationClient::MediaPlayerNotificationClient()");
}

MediaPlayerNotificationClient::~MediaPlayerNotificationClient() {
    SL_LOGV("MediaPlayerNotificationClient::~MediaPlayerNotificationClient()");
}

// Map a media_event_type enum (the msg of an IMediaPlayerClient::notify) to a string or NULL
static const char *media_event_type_to_string(media_event_type msg)
{
    switch (msg) {
#define _(code) case code: return #code;
    _(MEDIA_NOP)
    _(MEDIA_PREPARED)
    _(MEDIA_PLAYBACK_COMPLETE)
    _(MEDIA_BUFFERING_UPDATE)
    _(MEDIA_SEEK_COMPLETE)
    _(MEDIA_SET_VIDEO_SIZE)
    _(MEDIA_TIMED_TEXT)
    _(MEDIA_ERROR)
    _(MEDIA_INFO)
#undef _
    default:
        return NULL;
    }
}

// Map a media_error_type enum (the ext1 of a MEDIA_ERROR event) to a string or NULL
static const char *media_error_type_to_string(media_error_type err)
{
    switch (err) {
#define _(code, msg) case code: return msg;
    _(MEDIA_ERROR_UNKNOWN,                              "Unknown media error")
    _(MEDIA_ERROR_SERVER_DIED,                          "Server died")
    _(MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK,   "Not valid for progressive playback")
#undef _
    default:
        return NULL;
    }
}

// Map a media_info_type enum (the ext1 of a MEDIA_INFO event) to a string or NULL
static const char *media_info_type_to_string(media_info_type info)
{
    switch (info) {
#define _(code, msg) case code: return msg;
    _(MEDIA_INFO_UNKNOWN,             "Unknown info")
    _(MEDIA_INFO_VIDEO_TRACK_LAGGING, "Video track lagging")
    _(MEDIA_INFO_BUFFERING_START,     "Buffering start")
    _(MEDIA_INFO_BUFFERING_END,       "Buffering end")
    _(MEDIA_INFO_NETWORK_BANDWIDTH,   "Network bandwidth")
    _(MEDIA_INFO_BAD_INTERLEAVING,    "Bad interleaving")
    _(MEDIA_INFO_NOT_SEEKABLE,        "Not seekable")
    _(MEDIA_INFO_METADATA_UPDATE,     "Metadata update")
#undef _
    default:
        return NULL;
    }
}

//--------------------------------------------------
// IMediaPlayerClient implementation
void MediaPlayerNotificationClient::notify(int msg, int ext1, int ext2, const Parcel *obj) {
    SL_LOGV("MediaPlayerNotificationClient::notify(msg=%s (%d), ext1=%d, ext2=%d)",
            media_event_type_to_string((enum media_event_type) msg), msg, ext1, ext2);

    sp<GenericMediaPlayer> genericMediaPlayer(mGenericMediaPlayer.promote());
    if (genericMediaPlayer == NULL) {
        SL_LOGW("MediaPlayerNotificationClient::notify after GenericMediaPlayer destroyed");
        return;
    }

    switch ((media_event_type) msg) {
      case MEDIA_PREPARED:
        {
        Mutex::Autolock _l(mLock);
        if (PREPARE_IN_PROGRESS == mPlayerPrepared) {
            mPlayerPrepared = PREPARE_COMPLETED_SUCCESSFULLY;
            mPlayerPreparedCondition.signal();
        } else {
            SL_LOGE("Unexpected MEDIA_PREPARED");
        }
        }
        break;

      case MEDIA_SET_VIDEO_SIZE:
        // only send video size updates if the player was flagged as having video, to avoid
        // sending video size updates of (0,0)
        // We're running on a different thread than genericMediaPlayer's ALooper thread,
        // so it would normally be racy to access fields within genericMediaPlayer.
        // But in this case mHasVideo is const, so it is safe to access.
        // Or alternatively, we could notify unconditionally and let it decide whether to handle.
        if (genericMediaPlayer->mHasVideo && (ext1 != 0 || ext2 != 0)) {
            genericMediaPlayer->notify(PLAYEREVENT_VIDEO_SIZE_UPDATE,
                    (int32_t)ext1 /*width*/, (int32_t)ext2 /*height*/, true /*async*/);
        }
        break;

      case MEDIA_SEEK_COMPLETE:
        genericMediaPlayer->seekComplete();
        break;

      case MEDIA_PLAYBACK_COMPLETE:
        genericMediaPlayer->notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/);
        break;

      case MEDIA_BUFFERING_UPDATE:
        // if we receive any out-of-range data, then clamp it to reduce further harm
        if (ext1 < 0) {
            SL_LOGE("MEDIA_BUFFERING_UPDATE %d%% < 0", ext1);
            ext1 = 0;
        } else if (ext1 > 100) {
            SL_LOGE("MEDIA_BUFFERING_UPDATE %d%% > 100", ext1);
            ext1 = 100;
        }
        // values received from Android framework for buffer fill level use percent,
        //   while SL/XA use permille, so does GenericPlayer
        genericMediaPlayer->bufferingUpdate(ext1 * 10 /*fillLevelPerMille*/);
        break;

      case MEDIA_ERROR:
        {
        SL_LOGV("MediaPlayerNotificationClient::notify(msg=MEDIA_ERROR, ext1=%s (%d), ext2=%d)",
                media_error_type_to_string((media_error_type) ext1), ext1, ext2);
        Mutex::Autolock _l(mLock);
        if (PREPARE_IN_PROGRESS == mPlayerPrepared) {
            mPlayerPrepared = PREPARE_COMPLETED_UNSUCCESSFULLY;
            mPlayerPreparedCondition.signal();
        } else {
            // inform client of errors after preparation
            genericMediaPlayer->notify(PLAYEREVENT_ERRORAFTERPREPARE, ext1, true /*async*/);
        }
        }
        break;

      case MEDIA_NOP:
      case MEDIA_TIMED_TEXT:
        break;

      case MEDIA_INFO:
        SL_LOGV("MediaPlayerNotificationClient::notify(msg=MEDIA_INFO, ext1=%s (%d), ext2=%d)",
                media_info_type_to_string((media_info_type) ext1), ext1, ext2);
        switch (ext1) {
        case MEDIA_INFO_VIDEO_TRACK_LAGGING:
            SL_LOGV("MEDIA_INFO_VIDEO_TRACK_LAGGING by %d ms", ext1);
            break;
        case MEDIA_INFO_NETWORK_BANDWIDTH:
            SL_LOGV("MEDIA_INFO_NETWORK_BANDWIDTH %d kbps", ext2);
            break;
        case MEDIA_INFO_UNKNOWN:
        case MEDIA_INFO_BUFFERING_START:
        case MEDIA_INFO_BUFFERING_END:
        case MEDIA_INFO_BAD_INTERLEAVING:
        case MEDIA_INFO_NOT_SEEKABLE:
        case MEDIA_INFO_METADATA_UPDATE:
        default:
            break;
        }
        break;

      default:
        break;
    }

}

//--------------------------------------------------
void MediaPlayerNotificationClient::beforePrepare()
{
    Mutex::Autolock _l(mLock);
    assert(mPlayerPrepared == PREPARE_NOT_STARTED);
    mPlayerPrepared = PREPARE_IN_PROGRESS;
}

//--------------------------------------------------
bool MediaPlayerNotificationClient::blockUntilPlayerPrepared() {
    Mutex::Autolock _l(mLock);
    assert(mPlayerPrepared != PREPARE_NOT_STARTED);
    while (mPlayerPrepared == PREPARE_IN_PROGRESS) {
        mPlayerPreparedCondition.wait(mLock);
    }
    assert(mPlayerPrepared == PREPARE_COMPLETED_SUCCESSFULLY ||
            mPlayerPrepared == PREPARE_COMPLETED_UNSUCCESSFULLY);
    return mPlayerPrepared == PREPARE_COMPLETED_SUCCESSFULLY;
}

//--------------------------------------------------------------------------------------------------
GenericMediaPlayer::GenericMediaPlayer(const AudioPlayback_Parameters* params, bool hasVideo) :
    GenericPlayer(params),
    mHasVideo(hasVideo),
    mSeekTimeMsec(0),
    mVideoSurfaceTexture(0),
    mPlayer(0),
    mPlayerClient(new MediaPlayerNotificationClient(this)),
    mPlayerDeathNotifier(new MediaPlayerDeathNotifier(mPlayerClient))
{
    SL_LOGD("GenericMediaPlayer::GenericMediaPlayer()");

}

GenericMediaPlayer::~GenericMediaPlayer() {
    SL_LOGD("GenericMediaPlayer::~GenericMediaPlayer()");
}

void GenericMediaPlayer::preDestroy() {
    // FIXME can't access mPlayer from outside the looper (no mutex!) so using mPreparedPlayer
    sp<IMediaPlayer> player;
    getPreparedPlayer(player);
    if (player != NULL) {
        player->stop();
        // causes CHECK failure in Nuplayer, but commented out in the subclass preDestroy
        // randomly causes a NPE in StagefrightPlayer, heap corruption, or app hang
        //player->setDataSource(NULL);
        player->setVideoSurfaceTexture(NULL);
        player->disconnect();
        // release all references to the IMediaPlayer
        // FIXME illegal if not on looper
        //mPlayer.clear();
        {
            Mutex::Autolock _l(mPreparedPlayerLock);
            mPreparedPlayer.clear();
        }
    }
    GenericPlayer::preDestroy();
}

//--------------------------------------------------
// overridden from GenericPlayer
// pre-condition:
//   msec != NULL
// post-condition
//   *msec ==
//                  ANDROID_UNKNOWN_TIME if position is unknown at time of query,
//               or the current MediaPlayer position
void GenericMediaPlayer::getPositionMsec(int* msec) {
    SL_LOGD("GenericMediaPlayer::getPositionMsec()");
    sp<IMediaPlayer> player;
    getPreparedPlayer(player);
    // To avoid deadlock, directly call the MediaPlayer object
    if (player == 0 || player->getCurrentPosition(msec) != NO_ERROR) {
        *msec = ANDROID_UNKNOWN_TIME;
    }
}

//--------------------------------------------------
void GenericMediaPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
    SL_LOGV("GenericMediaPlayer::setVideoSurfaceTexture()");
    // FIXME bug - race condition, should do in looper
    if (mVideoSurfaceTexture.get() == surfaceTexture.get()) {
        return;
    }
    if ((mStateFlags & kFlagPrepared) && (mPlayer != 0)) {
        mPlayer->setVideoSurfaceTexture(surfaceTexture);
    }
    mVideoSurfaceTexture = surfaceTexture;
}


//--------------------------------------------------
// Event handlers

// blocks until mPlayer is prepared
void GenericMediaPlayer::onPrepare() {
    SL_LOGD("GenericMediaPlayer::onPrepare()");
    // Attempt to prepare at most once, and only if there is a MediaPlayer
    if (!(mStateFlags & (kFlagPrepared | kFlagPreparedUnsuccessfully)) && (mPlayer != 0)) {
        if (mHasVideo) {
            if (mVideoSurfaceTexture != 0) {
                mPlayer->setVideoSurfaceTexture(mVideoSurfaceTexture);
            }
        }
        mPlayer->setAudioStreamType(mPlaybackParams.streamType);
        mPlayerClient->beforePrepare();
        mPlayer->prepareAsync();
        if (mPlayerClient->blockUntilPlayerPrepared()) {
            mStateFlags |= kFlagPrepared;
            afterMediaPlayerPreparedSuccessfully();
        } else {
            mStateFlags |= kFlagPreparedUnsuccessfully;
        }
    }
    GenericPlayer::onPrepare();
    SL_LOGD("GenericMediaPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags);
}


void GenericMediaPlayer::onPlay() {
    SL_LOGD("GenericMediaPlayer::onPlay()");
    if (((mStateFlags & (kFlagPrepared | kFlagPlaying)) == kFlagPrepared) && (mPlayer != 0)) {
        mPlayer->start();
    }
    GenericPlayer::onPlay();
}


void GenericMediaPlayer::onPause() {
    SL_LOGD("GenericMediaPlayer::onPause()");
    if (!(~mStateFlags & (kFlagPrepared | kFlagPlaying)) && (mPlayer != 0)) {
        mPlayer->pause();
    }
    GenericPlayer::onPause();
}


void GenericMediaPlayer::onSeekComplete() {
    SL_LOGV("GenericMediaPlayer::onSeekComplete()");
    // did we initiate the seek?
    if (!(mStateFlags & kFlagSeeking)) {
        // no, are we looping?
        if (mStateFlags & kFlagLooping) {
            // yes, per OpenSL ES 1.0.1 and 1.1 do NOT report it to client
            // notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/);
        // no, well that's surprising, but it's probably just a benign race condition
        } else {
            SL_LOGW("Unexpected seek complete event ignored");
        }
    }
    GenericPlayer::onSeekComplete();
}


/**
 * pre-condition: WHATPARAM_SEEK_SEEKTIME_MS parameter value >= 0
 */
void GenericMediaPlayer::onSeek(const sp<AMessage> &msg) {
    SL_LOGV("GenericMediaPlayer::onSeek");
    int64_t timeMsec = ANDROID_UNKNOWN_TIME;
    if (!msg->findInt64(WHATPARAM_SEEK_SEEKTIME_MS, &timeMsec)) {
        // invalid command, drop it
        return;
    }
    if ((mStateFlags & kFlagSeeking) && (timeMsec == mSeekTimeMsec) &&
            (timeMsec != ANDROID_UNKNOWN_TIME)) {
        // already seeking to the same non-unknown time, cancel this command
        return;
    } else if (mStateFlags & kFlagPreparedUnsuccessfully) {
        // discard seeks after unsuccessful prepare
    } else if (!(mStateFlags & kFlagPrepared)) {
        // we are not ready to accept a seek command at this time, retry later
        msg->post(DEFAULT_COMMAND_DELAY_FOR_REPOST_US);
    } else {
        if (mPlayer != 0) {
            mStateFlags |= kFlagSeeking;
            mSeekTimeMsec = (int32_t)timeMsec;
            // seek to unknown time is used by StreamPlayer after discontinuity
            if (timeMsec == ANDROID_UNKNOWN_TIME) {
                // FIXME simulate a MEDIA_SEEK_COMPLETE event in 250 ms;
                // this is a terrible hack to make up for mediaserver not sending one
                (new AMessage(kWhatSeekComplete, id()))->post(250000);
            } else if (OK != mPlayer->seekTo(timeMsec)) {
                mStateFlags &= ~kFlagSeeking;
                mSeekTimeMsec = ANDROID_UNKNOWN_TIME;
                // don't call updateOneShot because seek not yet done
            }
        }
    }
}


void GenericMediaPlayer::onLoop(const sp<AMessage> &msg) {
    SL_LOGV("GenericMediaPlayer::onLoop");
    int32_t loop = 0;
    if (msg->findInt32(WHATPARAM_LOOP_LOOPING, &loop)) {
        if (loop) {
            mStateFlags |= kFlagLooping;
        } else {
            mStateFlags &= ~kFlagLooping;
        }
        // if we have a MediaPlayer then tell it now, otherwise we'll tell it after it's created
        if (mPlayer != 0) {
            (void) mPlayer->setLooping(loop);
        }
    }
}


void GenericMediaPlayer::onVolumeUpdate() {
    SL_LOGD("GenericMediaPlayer::onVolumeUpdate()");
    if (mPlayer != 0) {
        // use settings lock to read the volume settings
        Mutex::Autolock _l(mSettingsLock);
        mPlayer->setVolume(mAndroidAudioLevels.mFinalVolume[0],
                mAndroidAudioLevels.mFinalVolume[1]);
    }
}


void GenericMediaPlayer::onAttachAuxEffect(const sp<AMessage> &msg) {
    SL_LOGD("GenericMediaPlayer::onAttachAuxEffect()");
    int32_t effectId = 0;
    if (msg->findInt32(WHATPARAM_ATTACHAUXEFFECT, &effectId)) {
        if (mPlayer != 0) {
            status_t status;
            status = mPlayer->attachAuxEffect(effectId);
            // attachAuxEffect returns a status but we have no way to report it back to app
            (void) status;
        }
    }
}


void GenericMediaPlayer::onSetAuxEffectSendLevel(const sp<AMessage> &msg) {
    SL_LOGD("GenericMediaPlayer::onSetAuxEffectSendLevel()");
    float level = 0.0f;
    if (msg->findFloat(WHATPARAM_SETAUXEFFECTSENDLEVEL, &level)) {
        if (mPlayer != 0) {
            status_t status;
            status = mPlayer->setAuxEffectSendLevel(level);
            // setAuxEffectSendLevel returns a status but we have no way to report it back to app
            (void) status;
        }
    }
}


void GenericMediaPlayer::onBufferingUpdate(const sp<AMessage> &msg) {
    int32_t fillLevel = 0;
    if (msg->findInt32(WHATPARAM_BUFFERING_UPDATE, &fillLevel)) {
        SL_LOGD("GenericMediaPlayer::onBufferingUpdate(fillLevel=%d)", fillLevel);

        Mutex::Autolock _l(mSettingsLock);
        mCacheFill = fillLevel;
        // handle cache fill update
        if (mCacheFill - mLastNotifiedCacheFill >= mCacheFillNotifThreshold) {
            notifyCacheFill();
        }
        // handle prefetch status update
        //   compute how much time ahead of position is buffered
        int durationMsec, positionMsec = -1;
        if ((mStateFlags & kFlagPrepared) && (mPlayer != 0)
                && (OK == mPlayer->getDuration(&durationMsec))
                        && (OK == mPlayer->getCurrentPosition(&positionMsec))) {
            if ((-1 != durationMsec) && (-1 != positionMsec)) {
                // evaluate prefetch status based on buffer time thresholds
                int64_t bufferedDurationMsec = (durationMsec * fillLevel / 100) - positionMsec;
                CacheStatus_t newCacheStatus = mCacheStatus;
                if (bufferedDurationMsec > DURATION_CACHED_HIGH_MS) {
                    newCacheStatus = kStatusHigh;
                } else if (bufferedDurationMsec > DURATION_CACHED_MED_MS) {
                    newCacheStatus = kStatusEnough;
                } else if (bufferedDurationMsec > DURATION_CACHED_LOW_MS) {
                    newCacheStatus = kStatusIntermediate;
                } else if (bufferedDurationMsec == 0) {
                    newCacheStatus = kStatusEmpty;
                } else {
                    newCacheStatus = kStatusLow;
                }

                if (newCacheStatus != mCacheStatus) {
                    mCacheStatus = newCacheStatus;
                    notifyStatus();
                }
            }
        }
    } else {
        SL_LOGV("GenericMediaPlayer::onBufferingUpdate(fillLevel=unknown)");
    }
}


//--------------------------------------------------
/**
 * called from GenericMediaPlayer::onPrepare after the MediaPlayer mPlayer is prepared successfully
 * pre-conditions:
 *  mPlayer != 0
 *  mPlayer is prepared successfully
 */
void GenericMediaPlayer::afterMediaPlayerPreparedSuccessfully() {
    SL_LOGV("GenericMediaPlayer::afterMediaPlayerPrepared()");
    assert(mPlayer != 0);
    assert(mStateFlags & kFlagPrepared);
    // Mark this player as prepared successfully, so safe to directly call getCurrentPosition
    {
        Mutex::Autolock _l(mPreparedPlayerLock);
        assert(mPreparedPlayer == 0);
        mPreparedPlayer = mPlayer;
    }
    // retrieve channel count
    int32_t channelCount;
    Parcel *reply = new Parcel();
    status_t status = mPlayer->getParameter(KEY_PARAMETER_AUDIO_CHANNEL_COUNT, reply);
    if (status == NO_ERROR) {
        channelCount = reply->readInt32();
    } else {
        // FIXME MPEG-2 TS doesn't yet implement this key, so default to stereo
        channelCount = 2;
    }
    if (UNKNOWN_NUMCHANNELS != channelCount) {
        // now that we know the channel count, re-calculate the volumes
        notify(PLAYEREVENT_CHANNEL_COUNT, channelCount, true /*async*/);
    } else {
        LOGW("channel count is still unknown after prepare");
    }
    delete reply;
    // retrieve duration
    {
        int msec = 0;
        if (OK == mPlayer->getDuration(&msec)) {
            Mutex::Autolock _l(mSettingsLock);
            mDurationMsec = msec;
        }
    }
    // now that we have a MediaPlayer, set the looping flag
    if (mStateFlags & kFlagLooping) {
        (void) mPlayer->setLooping(1);
    }
    // when the MediaPlayer mPlayer is prepared, there is "sufficient data" in the playback buffers
    // if the data source was local, and the buffers are considered full so we need to notify that
    bool isLocalSource = true;
    if (kDataLocatorUri == mDataLocatorType) {
        isLocalSource = !isDistantProtocol(mDataLocator.uriRef);
    }
    if (isLocalSource) {
        SL_LOGD("media player prepared on local source");
        {
            Mutex::Autolock _l(mSettingsLock);
            mCacheStatus = kStatusHigh;
            mCacheFill = 1000;
            notifyStatus();
            notifyCacheFill();
        }
    } else {
        SL_LOGD("media player prepared on non-local source");
    }
}


//--------------------------------------------------
// If player is prepared successfully, set output parameter to that reference, otherwise NULL
void GenericMediaPlayer::getPreparedPlayer(sp<IMediaPlayer> &preparedPlayer)
{
    Mutex::Autolock _l(mPreparedPlayerLock);
    preparedPlayer = mPreparedPlayer;
}

} // namespace android
