Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa0315f9 authored by Marco Nelissen's avatar Marco Nelissen Committed by Android (Google) Code Review
Browse files

Merge "Add AMediaCodec callback"

parents 99119b45 cdb42cdc
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ enum {
    AMEDIACODEC_INFO_TRY_AGAIN_LATER = -1
};


/**
 * Create codec by name. Use this if you know the exact codec you want to use.
 * When configuring, you will need to specify whether to use the codec as an
@@ -140,6 +139,17 @@ int AMediaCodec_releaseOutputBuffer(AMediaCodec*, size_t idx, bool render);



typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);

/**
 * Set a callback to be called when a new buffer is available, or there was a format
 * or buffer change.
 * Note that you cannot perform any operations on the mediacodec from within the callback.
 * If you need to perform mediacodec operations, you must do so on a different thread.
 */
int AMediaCodec_setNotificationCallback(AMediaCodec*, OnCodecEvent callback, void *userdata);


#ifdef __cplusplus
} // extern "C"
#endif
+106 −13
Original line number Diff line number Diff line
@@ -45,26 +45,94 @@ static int translate_error(status_t err) {
    return -1000;
}

enum {
    kWhatActivityNotify,
    kWhatRequestActivityNotifications,
    kWhatStopActivityNotifications,
};


class CodecHandler: public AHandler {
private:
    AMediaCodec* mCodec;
public:
    CodecHandler(sp<android::MediaCodec>);
    CodecHandler(AMediaCodec *codec);
    virtual void onMessageReceived(const sp<AMessage> &msg);
};

CodecHandler::CodecHandler(sp<android::MediaCodec>) {
struct AMediaCodec {
    sp<android::MediaCodec> mCodec;
    sp<ALooper> mLooper;
    sp<CodecHandler> mHandler;
    sp<AMessage> mActivityNotification;
    int32_t mGeneration;
    bool mRequestedActivityNotification;
    OnCodecEvent mCallback;
    void *mCallbackUserData;
};

CodecHandler::CodecHandler(AMediaCodec *codec) {
    mCodec = codec;
}

void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
    ALOGI("handler got message %d", msg->what());

    switch (msg->what()) {
        case kWhatRequestActivityNotifications:
        {
            if (mCodec->mRequestedActivityNotification) {
                break;
            }

struct AMediaCodec {
    sp<android::MediaCodec> mCodec;
    sp<ALooper> mLooper;
    sp<CodecHandler> mHandler;
};
            mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
            mCodec->mRequestedActivityNotification = true;
            break;
        }

        case kWhatActivityNotify:
        {
            {
                int32_t generation;
                msg->findInt32("generation", &generation);

                if (generation != mCodec->mGeneration) {
                    // stale
                    break;
                }

                mCodec->mRequestedActivityNotification = false;
            }

            if (mCodec->mCallback) {
                mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
            }
            break;
        }

        case kWhatStopActivityNotifications:
        {
            uint32_t replyID;
            msg->senderAwaitsResponse(&replyID);

            mCodec->mGeneration++;
            mCodec->mRequestedActivityNotification = false;

            sp<AMessage> response = new AMessage;
            response->postReply(replyID);
            break;
        }

        default:
            ALOGE("shouldn't be here");
            break;
    }

}


static void requestActivityNotification(AMediaCodec *codec) {
    (new AMessage(kWhatRequestActivityNotifications, codec->mHandler->id()))->post();
}

extern "C" {

@@ -76,14 +144,17 @@ static AMediaCodec * createAMediaCodec(const char *name, bool name_is_type, bool
            false,      // runOnCallingThread
            true,       // canCallJava XXX
            PRIORITY_FOREGROUND);
    ALOGV("looper start: %d", ret);
    if (name_is_type) {
        mData->mCodec = android::MediaCodec::CreateByType(mData->mLooper, name, encoder);
    } else {
        mData->mCodec = android::MediaCodec::CreateByComponentName(mData->mLooper, name);
    }
    mData->mHandler = new CodecHandler(mData->mCodec);
    mData->mHandler = new CodecHandler(mData);
    mData->mLooper->registerHandler(mData->mHandler);
    mData->mGeneration = 1;
    mData->mRequestedActivityNotification = false;
    mData->mCallback = NULL;

    return mData;
}

@@ -129,11 +200,25 @@ int AMediaCodec_configure(
}

int AMediaCodec_start(AMediaCodec *mData) {
    return translate_error(mData->mCodec->start());
    status_t ret =  mData->mCodec->start();
    if (ret != OK) {
        return translate_error(ret);
    }
    mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler->id());
    mData->mActivityNotification->setInt32("generation", mData->mGeneration);
    requestActivityNotification(mData);
    return OK;
}

int AMediaCodec_stop(AMediaCodec *mData) {
    return translate_error(mData->mCodec->stop());
    int ret = translate_error(mData->mCodec->stop());

    sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler->id());
    sp<AMessage> response;
    msg->postAndAwaitResponse(&response);
    mData->mActivityNotification.clear();

    return ret;
}

int AMediaCodec_flush(AMediaCodec *mData) {
@@ -143,6 +228,7 @@ int AMediaCodec_flush(AMediaCodec *mData) {
ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
    size_t idx;
    status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
    requestActivityNotification(mData);
    if (ret == OK) {
        return idx;
    }
@@ -200,7 +286,7 @@ ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
    int64_t presentationTimeUs;
    status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
            &flags, timeoutUs);

    requestActivityNotification(mData);
    switch (ret) {
        case OK:
            info->offset = offset;
@@ -234,5 +320,12 @@ int AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render)
    }
}

int AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback, void *userdata) {
    mData->mCallback = callback;
    mData->mCallbackUserData = userdata;
    return OK;
}


} // extern "C"