status_t AACWriter::threadFunc() {
    mEstimatedDurationUs = 0;
    mEstimatedSizeBytes = 0;
    int64_t previousPausedDurationUs = 0;
    int64_t maxTimestampUs = 0;
    status_t err = OK;

    prctl(PR_SET_NAME, (unsigned long)"AACWriterThread", 0, 0, 0);

    while (!mDone && err == OK) {
        MediaBuffer *buffer;
        err = mSource->read(&buffer);

        if (err != OK) {
            break;
        }

        if (mPaused) {
            buffer->release();
            buffer = NULL;
            continue;
        }

        mEstimatedSizeBytes += kAdtsHeaderLength + buffer->range_length();
        if (exceedsFileSizeLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
            break;
        }

        int32_t isCodecSpecific = 0;
        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecSpecific) && isCodecSpecific) {
            ALOGV("Drop codec specific info buffer");
            buffer->release();
            buffer = NULL;
            continue;
        }

        int64_t timestampUs;
        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
        if (timestampUs > mEstimatedDurationUs) {
            mEstimatedDurationUs = timestampUs;
        }
        if (mResumed) {
            previousPausedDurationUs += (timestampUs - maxTimestampUs - mFrameDurationUs);
            mResumed = false;
        }
        timestampUs -= previousPausedDurationUs;
        ALOGV("time stamp: %lld, previous paused duration: %lld",
            timestampUs, previousPausedDurationUs);
        if (timestampUs > maxTimestampUs) {
            maxTimestampUs = timestampUs;
        }

        if (exceedsFileDurationLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
            break;
        }

        // Each output AAC audio frame to the file contains
        // 1. an ADTS header, followed by
        // 2. the compressed audio data.
        ssize_t dataLength = buffer->range_length();
        uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset();
        if (writeAdtsHeader(kAdtsHeaderLength + dataLength) != OK ||
            dataLength != write(mFd, data, dataLength)) {
            err = ERROR_IO;
        }

        buffer->release();
        buffer = NULL;
    }

    close(mFd);
    mFd = -1;
    mReachedEOS = true;
    if (err == ERROR_END_OF_STREAM) {
        return OK;
    }
    return err;
}
status_t AMRWriter::threadFunc() {
    mEstimatedDurationUs = 0;
    mEstimatedSizeBytes = 0;
    bool stoppedPrematurely = true;
    int64_t previousPausedDurationUs = 0;
    int64_t maxTimestampUs = 0;
    status_t err = OK;

    prctl(PR_SET_NAME, (unsigned long)"AMRWriter", 0, 0, 0);
    while (!mDone) {
        MediaBuffer *buffer;
        err = mSource->read(&buffer);

        if (err != OK) {
            break;
        }

        if (mPaused) {
            buffer->release();
            buffer = NULL;
            continue;
        }

        mEstimatedSizeBytes += buffer->range_length();
        if (exceedsFileSizeLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
            break;
        }

        int64_t timestampUs;
        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
        if (timestampUs > mEstimatedDurationUs) {
            mEstimatedDurationUs = timestampUs;
        }
        if (mResumed) {
            previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
            mResumed = false;
        }
        timestampUs -= previousPausedDurationUs;
        ALOGV("time stamp: %lld, previous paused duration: %lld",
                timestampUs, previousPausedDurationUs);
        if (timestampUs > maxTimestampUs) {
            maxTimestampUs = timestampUs;
        }

        if (exceedsFileDurationLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
            break;
        }
        ssize_t n = write(mFd,
                        (const uint8_t *)buffer->data() + buffer->range_offset(),
                        buffer->range_length());

        if (n < (ssize_t)buffer->range_length()) {
            buffer->release();
            buffer = NULL;

            break;
        }

        // XXX: How to tell it is stopped prematurely?
        if (stoppedPrematurely) {
            stoppedPrematurely = false;
        }

        buffer->release();
        buffer = NULL;
    }

    if (stoppedPrematurely) {
        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
    }

    close(mFd);
    mFd = -1;
    mReachedEOS = true;
    if ((err == ERROR_END_OF_STREAM)||(err = -ETIMEDOUT)) {
        return OK;
    }
    return err;
}
status_t ExtendedWriter::threadFunc() {
    mEstimatedDurationUs = 0;
    mEstimatedSizeBytes = 0;
    bool stoppedPrematurely = true;
    int64_t previousPausedDurationUs = 0;
    int64_t maxTimestampUs = 0;
    status_t err = OK;

    pid_t tid  = gettid();
    androidSetThreadPriority(tid, ANDROID_PRIORITY_AUDIO);
    prctl(PR_SET_NAME, (unsigned long)"ExtendedWriter", 0, 0, 0);
    while (!mDone) {
        MediaBuffer *buffer;
        err = mSource->read(&buffer);

        if (err != OK) {
            break;
        }

        if (mPaused) {
            buffer->release();
            buffer = NULL;
            continue;
        }

        mEstimatedSizeBytes += buffer->range_length();
        if (exceedsFileSizeLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
            break;
        }

        int64_t timestampUs;
        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
        if (timestampUs > mEstimatedDurationUs) {
            mEstimatedDurationUs = timestampUs;
        }
        if (mResumed) {
            previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
            mResumed = false;
        }
        timestampUs -= previousPausedDurationUs;
        ALOGV("time stamp: %lld, previous paused duration: %lld",
                timestampUs, previousPausedDurationUs);
        if (timestampUs > maxTimestampUs) {
            maxTimestampUs = timestampUs;
        }

        if (exceedsFileDurationLimit()) {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
            break;
        }
        ssize_t n = fwrite(
                (const uint8_t *)buffer->data() + buffer->range_offset(),
                1,
                buffer->range_length(),
                mFile);
        mOffset += n;

        if (n < (ssize_t)buffer->range_length()) {
            buffer->release();
            buffer = NULL;

            break;
        }

        // XXX: How to tell it is stopped prematurely?
        if (stoppedPrematurely) {
            stoppedPrematurely = false;
        }

        buffer->release();
        buffer = NULL;
    }

    if (stoppedPrematurely) {
        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
    }

    if ( mFormat == AUDIO_FORMAT_QCELP ) {
        writeQCPHeader( );
    }
    else if ( mFormat == AUDIO_FORMAT_EVRC ) {
        writeEVRCHeader( );
    }

    fflush(mFile);
    fclose(mFile);
    mFile = NULL;
    mReachedEOS = true;
    if (err == ERROR_END_OF_STREAM || (err == -ETIMEDOUT)) {
        return OK;
    }
    return err;
}
Beispiel #4
0
status_t OggWriter::threadFunc()
{
    mEstimatedDurationUs = 0;
    mEstimatedSizeBytes = 0;
    bool stoppedPrematurely = true;
    int64_t previousPausedDurationUs = 0;
    int64_t maxTimestampUs = 0;
    status_t err = OK;
    int64_t ltotalSize = 0;
    int64_t timestampUs = 0;
    //
    int64_t tsUsPauseBeg = 0;
    int64_t tsUsPauseEnd = 0;
    //paused sample count
    int64_t smpPaused = 0;
    //
    prctl(PR_SET_NAME, (unsigned long)"OggWriter", 0, 0, 0);

    //struct sched_param param;
    //param.sched_priority = RTPM_PRIO_OMX_AUDIO;
    //sched_setscheduler(0, SCHED_RR, &param);
    //androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
    //while (!mDone) {
    while (1 == 1)
    {
        MediaBuffer *buffer = NULL;
        MediaBuffer *buffer1 = NULL;

        if (mDone)
        {
            buffer = new MediaBuffer(0);
            buffer1 = buffer;
        }

        LOGV("OggWriter::threadFunc:mSource->read+:buffer=%p,buffer1=%p", buffer, buffer1);
        err = mSource->read(&buffer);
        LOGV("OggWriter::threadFunc:mSource->read-,err=%d,buffer=%p", err, buffer);

        if (err != OK)
        {
            break;
        }

        LOGV("OggWriter::threadFunc:buffer->range_length()=%d", buffer->range_length());

        //buffer->range_length() == 0, ogg encoder SWIP caching data
        if (mPaused || buffer->range_length() == 0)
        {
            //mtk80721 deal pause time error+
            if (mPaused && mPausedflag)
            {
                buffer->meta_data()->findInt64(kKeyTime, &tsUsPauseBeg);
                LOGD("OggWriter::threadFunc,pausetime=%d,tsUsPauseBeg=%lld", iPausedTime, tsUsPauseBeg);
                mPausedflag =  false;
            }

            //-
            if (buffer->range_length() > 0)
            {
                //not vorbis header data should be released
                if (memcmp(buffer->data() + 29, "vorbis", 6) != 0)
                {
                    buffer->release();
                    buffer = NULL;
                    continue;
                }
                else
                {
                    LOGD("ogg header:buffer=%p,size=%d", buffer, buffer->range_length());
                }
            }
            else
            {
                buffer->release();
                buffer = NULL;
                continue;
            }
        }

        mEstimatedSizeBytes += buffer->range_length();

        if (exceedsFileSizeLimit())
        {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
            break;
        }

        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));

        if (timestampUs > 0)
        {
            if (timestampUs > mEstimatedDurationUs)
            {
                mEstimatedDurationUs = timestampUs;
            }

            if (mResumed)
            {
                //mtk80721 deal pause time error+
                buffer->meta_data()->findInt64(kKeyTime, &tsUsPauseEnd);
                LOGD("previousPausedDurationUs =%lld,pausetime=%d,tsUsPauseBeg=%lld,tsUsPauseEnd=%lld",
                     previousPausedDurationUs, iPausedTime, tsUsPauseBeg, tsUsPauseEnd);

                previousPausedDurationUs = previousPausedDurationUs + (tsUsPauseEnd - tsUsPauseBeg);
                smpPaused = previousPausedDurationUs * mSampleRate / 1000000ll;

                LOGD("previousPausedDurationUs =%lld,samplecount=%lld", previousPausedDurationUs, smpPaused);
                //previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
                //-
                mResumed = false;
            }

            timestampUs -= previousPausedDurationUs;
            LOGV("time stamp: %lld, previous paused duration: %lld", timestampUs, previousPausedDurationUs);

            if (timestampUs > maxTimestampUs)
            {
                maxTimestampUs = timestampUs;
            }
        }

        if (exceedsFileDurationLimit())
        {
            buffer->release();
            buffer = NULL;
            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
            break;
        }

        LOGV("OggWriter::threadFunc:fwrite");
        //write timestamp
        uint8_t *ptimestamp = (uint8_t *)buffer->data() + buffer->range_offset() + 6;
        uint64_t ts = U64LE_AT(ptimestamp);

        if (smpPaused > 0)
        {
            ts -= smpPaused;
            memcpy(ptimestamp, &ts, sizeof(int64_t));
        }

        ssize_t n = fwrite(
                        (const uint8_t *)buffer->data() + buffer->range_offset(),
                        1,
                        buffer->range_length(),
                        mFile);

        ltotalSize += n;

        if (n < (ssize_t)buffer->range_length())
        {
            buffer->release();
            buffer = NULL;
            break;
        }

        // XXX: How to tell it is stopped prematurely?
        if (stoppedPrematurely)
        {
            stoppedPrematurely = false;
        }

        LOGV("OggWriter::threadFunc:buffer->release:buffer=%p", buffer);
        buffer->release();
        buffer = NULL;
    }

    if (stoppedPrematurely)
    {
        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
    }

    /*
    //
        int bitrate = ltotalSize  / (timestampUs/1E6) * 8;
        LOGV("ltotalSize=%lld, timestampUs=%lld, bitrate=%d",ltotalSize, timestampUs, bitrate);
     //seek to the bitrate field
        fseek(mFile, 44, SEEK_SET);
     // max bitrate
        fwrite(&bitrate, 1, sizeof(int), mFile);
     // nominal bitrate
        fwrite(&bitrate, 1, sizeof(int), mFile);
     // min bitrate
        fwrite(&bitrate, 1, sizeof(int), mFile);
    */
    fflush(mFile);
    fclose(mFile);
    mFile = NULL;
    mReachedEOS = true;

    if (err == ERROR_END_OF_STREAM)
    {
        return OK;
    }

    return err;
}