/*
 * 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.
 */

#include "sles_allinclusive.h"

#include <media/IMediaPlayerService.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/IOMX.h>
#include <media/stagefright/MediaDefs.h>


namespace android {

// listed in same order as VideoCodecIds[] in file "../devices.c" with ANDROID defined
static const char *kVideoMimeTypes[] = {
        MEDIA_MIMETYPE_VIDEO_MPEG2,
        MEDIA_MIMETYPE_VIDEO_H263,
        MEDIA_MIMETYPE_VIDEO_MPEG4,
        MEDIA_MIMETYPE_VIDEO_AVC,
        MEDIA_MIMETYPE_VIDEO_VPX
};
// must == kMaxVideoDecoders
static const size_t kNbVideoMimeTypes = sizeof(kVideoMimeTypes) / sizeof(kVideoMimeTypes[0]);

// codec capabilities in the following arrays maps to the mime types defined in kVideoMimeTypes
// CodecCapabilities is from OMXCodec.h
static Vector<CodecCapabilities> VideoDecoderCapabilities[kNbVideoMimeTypes];
static XAuint32 VideoDecoderNbProfLevel[kNbVideoMimeTypes];

static XAuint32 NbSupportedDecoderTypes = 0;


XAuint32 convertOpenMaxIlToAl(OMX_U32 ilVideoProfileOrLevel) {
    // For video codec profiles and levels, the number of trailing zeroes in OpenMAX IL
    // are equal to the matching OpenMAX AL constant value plus 1, for example:
    //    XA_VIDEOPROFILE_H263_BACKWARDCOMPATIBLE ((XAuint32) 0x00000003)
    //        matches
    //    OMX_VIDEO_H263ProfileBackwardCompatible  = 0x04
    return (XAuint32) (__builtin_ctz(ilVideoProfileOrLevel) + 1);
}


bool android_videoCodec_expose() {
    SL_LOGV("android_videoCodec_expose()");

    sp<IMediaPlayerService> service(IMediaDeathNotifier::getMediaPlayerService());
    if (service == NULL) {
        // no need to SL_LOGE; getMediaPlayerService already will have done so
        return false;
    }

    sp<IOMX> omx(service->getOMX());
    if (omx.get() == NULL) {
        LOGE("android_videoCodec_expose() couldn't access OMX interface");
        return false;
    }

    // used to check whether no codecs were found, which is a sign of failure
    NbSupportedDecoderTypes = 0;
    for (size_t m = 0 ; m < kNbVideoMimeTypes ; m++) {
        // QueryCodecs is from OMXCodec.h
        if (OK == QueryCodecs(omx, kVideoMimeTypes[m], true /* queryDecoders */,
                true /* hwCodecOnly */, &VideoDecoderCapabilities[m])) {
            if (VideoDecoderCapabilities[m].empty()) {
                VideoDecoderNbProfLevel[m] = 0;
            } else {
                // get the number of profiles and levels for the first codec implementation
                // for a given decoder ID / MIME type
                Vector<CodecProfileLevel> &profileLevels =
                        VideoDecoderCapabilities[m].editItemAt(0).mProfileLevels;
#if 0   // Intentionally disabled example of making modifications to profile / level combinations
                if (VideoDecoderIds[m] == XA_VIDEOCODEC_AVC) {
                    // remove non-core profile / level combinations
                    for (size_t i = 0, size = profileLevels.size(); i < size; ) {
                        CodecProfileLevel profileLevel = profileLevels.itemAt(i);
                        if (profileLevel.mProfile == XA_VIDEOPROFILE_AVC_BASELINE) {
                            // either skip past this item and don't change vector size
                            ++i;
                        } else {
                            // or remove this item, decrement the vector size,
                            // and next time through the loop check a different item at same index
                            profileLevels.removeAt(i);
                            --size;
                        }
                    }
                }
#endif
                if ((VideoDecoderNbProfLevel[m] = profileLevels.size()) > 0) {
                    NbSupportedDecoderTypes++;
                } else {
                    VideoDecoderCapabilities[m].clear();
                }
            }
        }
    }

    return (NbSupportedDecoderTypes > 0);
}


void android_videoCodec_deinit() {
    SL_LOGV("android_videoCodec_deinit()");
    for (size_t m = 0 ; m < kNbVideoMimeTypes ; m++) {
        VideoDecoderCapabilities[m].clear();
    }
    // not needed
    // memset(VideoDecoderNbProfLevel, 0, sizeof(VideoDecoderNbProfLevel));
    // NbSupportedDecoderTypes = 0;
}


XAuint32 android_videoCodec_getNbDecoders() {
    return NbSupportedDecoderTypes;
}


void android_videoCodec_getDecoderIds(XAuint32 nbDecoders, XAuint32 *pDecoderIds) {
    XAuint32 *pIds = pDecoderIds;
    XAuint32 nbFound = 0;
    for (size_t m = 0 ; m < kNbVideoMimeTypes ; m++) {
        if (!VideoDecoderCapabilities[m].empty()) {
            *pIds = VideoDecoderIds[m];
            pIds++;
            nbFound++;
        }
        // range check: function can be called for fewer codecs than there are
        if (nbFound == nbDecoders) {
            break;
        }
    }
}


SLresult android_videoCodec_getProfileLevelCombinationNb(XAuint32 decoderId, XAuint32 *pNb)
{
    // translate a decoder ID to an index in the codec table
    size_t decoderIndex = 0;
    while (decoderIndex < kNbVideoMimeTypes) {
        if (decoderId == VideoDecoderIds[decoderIndex]) {
            *pNb = VideoDecoderNbProfLevel[decoderIndex];
            return XA_RESULT_SUCCESS;
        }
        decoderIndex++;
    }

    // spec doesn't allow a decoder to report zero profile/level combinations
    *pNb = 0;
    return XA_RESULT_PARAMETER_INVALID;
}


SLresult android_videoCodec_getProfileLevelCombination(XAuint32 decoderId, XAuint32 plIndex,
        XAVideoCodecDescriptor *pDescr)
{
    // translate a decoder ID to an index in the codec table
    size_t decoderIndex = 0;
    while (decoderIndex < kNbVideoMimeTypes) {
        if (decoderId == VideoDecoderIds[decoderIndex]) {
            // We only look at the first codec implementation for a given decoder ID / MIME type.
            // OpenMAX AL doesn't let you expose the capabilities of multiple codec implementations.
            if (!(plIndex < VideoDecoderCapabilities[decoderIndex].itemAt(0).mProfileLevels.size()))
            {
                // asking for invalid profile/level
                return XA_RESULT_PARAMETER_INVALID;
            }
            //     set the fields we know about
            pDescr->codecId = decoderId;
            pDescr->profileSetting = convertOpenMaxIlToAl(VideoDecoderCapabilities[decoderIndex].
                    itemAt(0).mProfileLevels.itemAt(plIndex).mProfile);
            pDescr->levelSetting =  convertOpenMaxIlToAl(VideoDecoderCapabilities[decoderIndex].
                    itemAt(0).mProfileLevels.itemAt(plIndex).mLevel);
            //     initialize the fields we don't know about
            pDescr->maxWidth = 0;
            pDescr->maxHeight = 0;
            pDescr->maxFrameRate = 0;
            pDescr->maxBitRate = 0;
            pDescr->rateControlSupported = 0;
            break;
        }
        decoderIndex++;
    }
    return (decoderIndex < kNbVideoMimeTypes) ? XA_RESULT_SUCCESS : XA_RESULT_PARAMETER_INVALID;
}

} // namespace android
