/*
 * 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 <system/window.h>

#include <media/IMediaPlayerService.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 {
        ALOGW("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
