int Encoder_Interface_Encode(void* s, enum Mode mode, const short* in, unsigned char* out) {
	struct encoder_state* state = (struct encoder_state*) s;
	enum Frame_Type_3GPP frame_type = (enum Frame_Type_3GPP) mode;
	int ret = AMREncode(state->encCtx, state->pidSyncCtx, mode, (Word16*) in, out, &frame_type, AMR_TX_IETF);
	out[0] |= 0x04;
	return ret;
}
int Encoder_Interface_Encode(void* s, enum Mode mode, 
							 const short* speech, unsigned char* out, 
							 int forceSpeech) {
	struct encoder_state* state = (struct encoder_state*) s;
	enum Frame_Type_3GPP frame_type = (enum Frame_Type_3GPP) mode;

	/**
	Word16 AMREncode(
    void *pEncState,   void *pSidSyncState,
    enum Mode 3gp_frame_type,
    Word16 *pEncInput,
	UWord8 *pEncOutput,

    enum Frame_Type_3GPP *p3gpp_frame_type,
    Word16 output_format
)
	*/
	int ret = AMREncode(state->encCtx, state->pidSyncCtx, 
						mode, 
						(Word16*) speech, 
						 out, 
						 &frame_type, 
						 AMR_TX_IETF);
	out[0] |= 0x04;
	return ret;
}
OSCL_EXPORT_REF int32 CPvGsmAmrEncoder::Encode(TInputAudioStream& aInStream,
        TOutputAudioStream& aOutStream)
{
    // check first if mode specified is invalid
    if (IsModeValid(aInStream.iMode) == false)
        return GSMAMR_ENC_INVALID_MODE;

    // set AMR mode for this set of samples
    iGsmAmrMode = (GSM_AMR_MODES)aInStream.iMode;

    // get the maximum number of frames // BX
    int32 bytesPerFrame = iNumSamplesPerFrame * iBytesPerSample;
    int32 maxNumFrames = aInStream.iSampleLength / bytesPerFrame;
    uint8 *pFrameIn  = aInStream.iSampleBuffer;
    uint8 *pFrameOut = aOutStream.iBitStreamBuffer;
    int32 i;

    // encode samples
    for (i = 0; i < maxNumFrames; i++)
    {

        // //////////////////////////////////////////
        // encode this frame
        // //////////////////////////////////////////
        int32 * temp = & iLastModeUsed;
        Word16 nStatus = AMREncode(iEncState, iSidState, 	// BX, Word16 instead of int32 to avoid wierd case(IF2 format): the function returns 31, but nStatus ends up with a big wierd number
                                   (Mode)iGsmAmrMode,
                                   (Word16 *)pFrameIn,
                                   (unsigned char *)pFrameOut,
                                   (Frame_Type_3GPP*) temp,
                                   iBitStreamFormat);

        if (nStatus < 0)
        {
            // an error when encoding was received, so quit
            return(GSMAMR_ENC_CODEC_ENCODE_FAILURE);
        }

        // save nStatus as this indicates the encoded frame size
        int32 encFrameSize = (int32)nStatus;
        aOutStream.iSampleFrameSize[i] = encFrameSize;
        pFrameOut += encFrameSize;
        pFrameIn  += bytesPerFrame;
    }

    // set other values to be returned
    aOutStream.iNumSampleFrames = maxNumFrames;
    return(GSMAMR_ENC_NO_ERROR);
}
int encode(int mode, const char *srcFile, const char *dstFile) {
    int           retVal     = EXIT_SUCCESS;
    FILE          *fSrc      = NULL;
    FILE          *fDst      = NULL;
    int           frameNum   = 0;
    bool          eofReached = false;
    uint16_t      *inputBuf  = NULL;
    uint8_t       *outputBuf = NULL;
    AmrNbEncState *amr       = NULL;

    clock_t   start, finish;
    double    duration = 0.0;

    // Open input file.
    fSrc = fopen(srcFile, "rb");
    if (fSrc == NULL) {
        fprintf(stderr, "Error opening input file\n");
        retVal = EXIT_FAILURE;
        goto safe_exit;
    }

    // Open output file.
    fDst = fopen(dstFile, "wb");
    if (fDst == NULL) {
        fprintf(stderr, "Error opening output file\n");
        retVal = EXIT_FAILURE;
        goto safe_exit;
    }

    // Allocate input buffer.
    inputBuf = (uint16_t*) malloc(kInputSize);
    assert(inputBuf != NULL);

    // Allocate output buffer.
    outputBuf = (uint8_t*) malloc(kOutputSize);
    assert(outputBuf != NULL);

    // Initialize encoder.
    amr = (AmrNbEncState*) malloc(sizeof(AmrNbEncState));
    AMREncodeInit(&amr->encCtx, &amr->pidSyncCtx, 0);

    // Write file header.
    fwrite("#!AMR\n", 1, 6, fDst);

    while (1) {
        // Read next input frame.
        int bytesRead;
        bytesRead = fread(inputBuf, 1, kInputSize, fSrc);
        if (bytesRead != kInputSize && !feof(fSrc)) {
            retVal = EXIT_FAILURE; // Invalid magic number.
            fprintf(stderr, "Error reading input file\n");
            goto safe_exit;
        } else if (feof(fSrc) && bytesRead == 0) {
            eofReached = true;
            break;
        }

        start = clock();

        // Encode the frame.
        Frame_Type_3GPP frame_type = (Frame_Type_3GPP) mode;
        int bytesGenerated;
        bytesGenerated = AMREncode(amr->encCtx, amr->pidSyncCtx, (Mode)mode,
                                   (Word16*)inputBuf, outputBuf, &frame_type,
                                   AMR_TX_WMF);

        // Convert from WMF to RFC 3267 format.
        if (bytesGenerated > 0) {
            outputBuf[0] = ((outputBuf[0] << 3) | 4) & 0x7c;
        }

        finish = clock();
        duration += finish - start;

        if (bytesGenerated < 0) {
            retVal = EXIT_FAILURE;
            fprintf(stderr, "Encoding error\n");
            goto safe_exit;
        }

        frameNum++;
        printf(" Frames processed: %d\n", frameNum);

        // Write the output.
        fwrite(outputBuf, 1, bytesGenerated, fDst);
    }

    // Dump the time taken by encode.
    printf("\n%2.5lf seconds\n", (double)duration/CLOCKS_PER_SEC);

safe_exit:

    // Free the encoder instance.
    if (amr) {
        AMREncodeExit(&amr->encCtx, &amr->pidSyncCtx);
        free(amr);
    }

    // Free input and output buffer.
    free(inputBuf);
    free(outputBuf);

    // Close the input and output files.
    if (fSrc) {
        fclose(fSrc);
    }
    if (fDst) {
        fclose(fDst);
    }

    return retVal;
}
void SoftAMRNBEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
    if (mSignalledError) {
        return;
    }

    List<BufferInfo *> &inQueue = getPortQueue(0);
    List<BufferInfo *> &outQueue = getPortQueue(1);

    size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);

    for (;;) {
        // We do the following until we run out of buffers.

        while (mInputSize < numBytesPerInputFrame) {
            // As long as there's still input data to be read we
            // will drain "kNumSamplesPerFrame" samples
            // into the "mInputFrame" buffer and then encode those
            // as a unit into an output buffer.

            if (mSawInputEOS || inQueue.empty()) {
                return;
            }

            BufferInfo *inInfo = *inQueue.begin();
            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

            const void *inData = inHeader->pBuffer + inHeader->nOffset;

            size_t copy = numBytesPerInputFrame - mInputSize;
            if (copy > inHeader->nFilledLen) {
                copy = inHeader->nFilledLen;
            }

            if (mInputSize == 0) {
                mInputTimeUs = inHeader->nTimeStamp;
            }

            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
            mInputSize += copy;

            inHeader->nOffset += copy;
            inHeader->nFilledLen -= copy;

            // "Time" on the input buffer has in effect advanced by the
            // number of audio frames we just advanced nOffset by.
            inHeader->nTimeStamp +=
                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);

            if (inHeader->nFilledLen == 0) {
                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                    ALOGV("saw input EOS");
                    mSawInputEOS = true;

                    // Pad any remaining data with zeroes.
                    memset((uint8_t *)mInputFrame + mInputSize,
                           0,
                           numBytesPerInputFrame - mInputSize);

                    mInputSize = numBytesPerInputFrame;
                }

                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);

                inData = NULL;
                inHeader = NULL;
                inInfo = NULL;
            }
        }

        // At this  point we have all the input data necessary to encode
        // a single frame, all we need is an output buffer to store the result
        // in.

        if (outQueue.empty()) {
            return;
        }

        BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

        uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;

        Frame_Type_3GPP frameType;
        int res = AMREncode(
                mEncState, mSidState, (Mode)mMode,
                mInputFrame, outPtr, &frameType, AMR_TX_WMF);

        CHECK_GE(res, 0);
        CHECK_LE((size_t)res, outAvailable);

        // Convert header byte from WMF to IETF format.
        outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;

        outHeader->nFilledLen = res;
        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;

        if (mSawInputEOS) {
            // We also tag this output buffer with EOS if it corresponds
            // to the final input buffer.
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
        }

        outHeader->nTimeStamp = mInputTimeUs;

#if 0
        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
              nOutputBytes, mInputTimeUs, outHeader->nFlags);

        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
#endif

        outQueue.erase(outQueue.begin());
        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        outHeader = NULL;
        outInfo = NULL;

        mInputSize = 0;
    }
}
status_t AMRNBEncoder::read(
        MediaBuffer **out, const ReadOptions *options) {
    status_t err;

    *out = NULL;

    int64_t seekTimeUs;
    ReadOptions::SeekMode mode;
    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
    bool readFromSource = false;
    int64_t wallClockTimeUs = -1;

    while (mNumInputSamples < kNumSamplesPerFrame) {
        if (mInputBuffer == NULL) {
            err = mSource->read(&mInputBuffer, options);

            if (err != OK) {
                if (mNumInputSamples == 0) {
                    return ERROR_END_OF_STREAM;
                }
                memset(&mInputFrame[mNumInputSamples],
                       0,
                       sizeof(int16_t)
                            * (kNumSamplesPerFrame - mNumInputSamples));
                mNumInputSamples = kNumSamplesPerFrame;
                break;
            }

            size_t align = mInputBuffer->range_length() % sizeof(int16_t);
            CHECK_EQ(align, 0);
            readFromSource = true;

            int64_t timeUs;
            if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
                wallClockTimeUs = timeUs;
            }
            if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
                mAnchorTimeUs = timeUs;
            }
        } else {
            readFromSource = false;
        }

        size_t copy =
            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);

        if (copy > mInputBuffer->range_length()) {
            copy = mInputBuffer->range_length();
        }

        memcpy(&mInputFrame[mNumInputSamples],
               (const uint8_t *)mInputBuffer->data()
                    + mInputBuffer->range_offset(),
               copy);

        mNumInputSamples += copy / sizeof(int16_t);

        mInputBuffer->set_range(
                mInputBuffer->range_offset() + copy,
                mInputBuffer->range_length() - copy);

        if (mInputBuffer->range_length() == 0) {
            mInputBuffer->release();
            mInputBuffer = NULL;
        }
    }

    MediaBuffer *buffer;
    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);

    uint8_t *outPtr = (uint8_t *)buffer->data();

    Frame_Type_3GPP frameType;
    int res = AMREncode(
            mEncState, mSidState, (Mode)mMode,
            mInputFrame, outPtr, &frameType, AMR_TX_WMF);

    CHECK(res >= 0);
    CHECK((size_t)res < buffer->size());

    // Convert header byte from WMF to IETF format.
    outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;

    buffer->set_range(0, res);

    // Each frame of 160 samples is 20ms long.
    int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
    buffer->meta_data()->setInt64(
            kKeyTime, mAnchorTimeUs + mediaTimeUs);

    if (readFromSource && wallClockTimeUs != -1) {
        buffer->meta_data()->setInt64(kKeyDriftTime,
            mediaTimeUs - wallClockTimeUs);
    }

    ++mNumFramesOutput;

    *out = buffer;

    mNumInputSamples = 0;

    return OK;
}