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

Commit 3bf8430e authored by James Dong's avatar James Dong Committed by Android Git Automerger
Browse files

am d6ec2175: am 65c83b90: Merge "Refactor Stagefright::StartMPEG4Recording()" into gingerbread

Merge commit 'd6ec2175'

* commit 'd6ec2175':
  Refactor Stagefright::StartMPEG4Recording()
parents 69fc43d4 d6ec2175
Loading
Loading
Loading
Loading
+179 −151
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ status_t StagefrightRecorder::setAudioSource(audio_source as) {
    LOGV("setAudioSource: %d", as);
    if (as < AUDIO_SOURCE_DEFAULT ||
        as >= AUDIO_SOURCE_LIST_END) {
        LOGE("Invalid audio source: %d", as);
        return BAD_VALUE;
    }

@@ -85,6 +86,7 @@ status_t StagefrightRecorder::setVideoSource(video_source vs) {
    LOGV("setVideoSource: %d", vs);
    if (vs < VIDEO_SOURCE_DEFAULT ||
        vs >= VIDEO_SOURCE_LIST_END) {
        LOGE("Invalid video source: %d", vs);
        return BAD_VALUE;
    }

@@ -101,6 +103,7 @@ status_t StagefrightRecorder::setOutputFormat(output_format of) {
    LOGV("setOutputFormat: %d", of);
    if (of < OUTPUT_FORMAT_DEFAULT ||
        of >= OUTPUT_FORMAT_LIST_END) {
        LOGE("Invalid output format: %d", of);
        return BAD_VALUE;
    }

@@ -117,6 +120,7 @@ status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
    LOGV("setAudioEncoder: %d", ae);
    if (ae < AUDIO_ENCODER_DEFAULT ||
        ae >= AUDIO_ENCODER_LIST_END) {
        LOGE("Invalid audio encoder: %d", ae);
        return BAD_VALUE;
    }

@@ -133,6 +137,7 @@ status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
    LOGV("setVideoEncoder: %d", ve);
    if (ve < VIDEO_ENCODER_DEFAULT ||
        ve >= VIDEO_ENCODER_LIST_END) {
        LOGE("Invalid video encoder: %d", ve);
        return BAD_VALUE;
    }

@@ -176,7 +181,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
    LOGV("setCamera");
    if (camera == 0) {
        LOGE("camera is NULL");
        return UNKNOWN_ERROR;
        return BAD_VALUE;
    }

    int64_t token = IPCThreadState::self()->clearCallingIdentity();
@@ -185,7 +190,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
    if (mCamera == 0) {
        LOGE("Unable to connect to camera");
        IPCThreadState::self()->restoreCallingIdentity(token);
        return UNKNOWN_ERROR;
        return -EBUSY;
    }

    LOGV("Connected to camera");
@@ -206,11 +211,11 @@ status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
}

status_t StagefrightRecorder::setOutputFile(const char *path) {
    LOGE("setOutputFile(const char*) should not be called");
    LOGE("setOutputFile(const char*) must not be called");
    // We don't actually support this at all, as the media_server process
    // no longer has permissions to create files.

    return UNKNOWN_ERROR;
    return -EPERM;
}

status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
@@ -219,6 +224,11 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng
    CHECK_EQ(offset, 0);
    CHECK_EQ(length, 0);

    if (fd < 0) {
        LOGE("Invalid file descriptor: %d", fd);
        return -EBADF;
    }

    if (mOutputFd >= 0) {
        ::close(mOutputFd);
    }
@@ -294,6 +304,7 @@ status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
    LOGV("setParamAudioNumberOfChannels: %d", channels);
    if (channels <= 0 || channels >= 3) {
        LOGE("Invalid number of audio channels: %d", channels);
        return BAD_VALUE;
    }

    // Additional check on the number of channels will be performed later.
@@ -331,21 +342,23 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
    return OK;
}

status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit,
        bool limit_is_duration) {
    LOGV("setParamMaxDurationOrFileSize: limit (%lld) for %s",
            limit, limit_is_duration?"duration":"size");
    if (limit_is_duration) {  // limit is in ms
        if (limit <= 1000) {  // XXX: 1 second
            LOGE("Max file duration is too short: %lld us", limit);
status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
    LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
    if (timeUs <= 1000000LL) {  // XXX: 1 second
        LOGE("Max file duration is too short: %lld us", timeUs);
        return BAD_VALUE;
    }
        mMaxFileDurationUs = limit * 1000LL;
    } else {
        if (limit <= 1024) {  // XXX: 1 kB
            LOGE("Max file size is too small: %lld bytes", limit);
    mMaxFileDurationUs = timeUs;
    return OK;
}
        mMaxFileSizeBytes = limit;

status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
    LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
    if (bytes <= 1024) {  // XXX: 1 kB
        LOGE("Max file size is too small: %lld bytes", bytes);
        return BAD_VALUE;
    }
    mMaxFileSizeBytes = bytes;
    return OK;
}

@@ -370,7 +383,7 @@ status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {

// If interval <  0, only the first frame is I frame, and rest are all P frames
// If interval == 0, all frames are encoded as I frames. No P frames
// If interval >  0, it is the time spacing between 2 neighboring I frames
// If interval >  0, it is the time spacing (seconds) between 2 neighboring I frames
status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) {
    LOGV("setParamVideoIFramesInterval: %d seconds", interval);
    mIFramesInterval = interval;
@@ -396,6 +409,7 @@ status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) {
    LOGV("setParamTrackFrameStatus: %d", nFrames);
    if (nFrames <= 0) {
        LOGE("Invalid number of frames to track: %d", nFrames);
        return BAD_VALUE;
    }
    mTrackEveryNumberOfFrames = nFrames;
@@ -405,6 +419,7 @@ status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) {
status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
    LOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
    if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
        LOGE("Tracking time duration too short: %lld us", timeDurationUs);
        return BAD_VALUE;
    }
    mTrackEveryTimeDurationUs = timeDurationUs;
@@ -417,14 +432,12 @@ status_t StagefrightRecorder::setParameter(
    if (key == "max-duration") {
        int64_t max_duration_ms;
        if (safe_strtoi64(value.string(), &max_duration_ms)) {
            return setParamMaxDurationOrFileSize(
                    max_duration_ms, true /* limit_is_duration */);
            return setParamMaxFileDurationUs(1000LL * max_duration_ms);
        }
    } else if (key == "max-filesize") {
        int64_t max_filesize_bytes;
        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
            return setParamMaxDurationOrFileSize(
                    max_filesize_bytes, false /* limit is filesize */);
            return setParamMaxFileSizeBytes(max_filesize_bytes);
        }
    } else if (key == "interleave-duration-us") {
        int32_t durationUs;
@@ -528,7 +541,10 @@ status_t StagefrightRecorder::prepare() {
}

status_t StagefrightRecorder::start() {
    CHECK(mOutputFd >= 0);

    if (mWriter != NULL) {
        LOGE("File writer is not avaialble");
        return UNKNOWN_ERROR;
    }

@@ -547,6 +563,7 @@ status_t StagefrightRecorder::start() {
            return startAACRecording();

        default:
            LOGE("Unsupported output file format: %d", mOutputFormat);
            return UNKNOWN_ERROR;
    }
}
@@ -610,7 +627,6 @@ status_t StagefrightRecorder::startAACRecording() {

    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
    CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
    CHECK(mOutputFd >= 0);

    CHECK(0 == "AACWriter is not implemented yet");

@@ -626,34 +642,34 @@ status_t StagefrightRecorder::startAMRRecording() {
            mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
            LOGE("Invalid encoder %d used for AMRNB recording",
                    mAudioEncoder);
            return UNKNOWN_ERROR;
            return BAD_VALUE;
        }
        if (mSampleRate != 8000) {
            LOGE("Invalid sampling rate %d used for AMRNB recording",
                    mSampleRate);
            return UNKNOWN_ERROR;
            return BAD_VALUE;
        }
    } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
        if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
            LOGE("Invlaid encoder %d used for AMRWB recording",
                    mAudioEncoder);
            return UNKNOWN_ERROR;
            return BAD_VALUE;
        }
        if (mSampleRate != 16000) {
            LOGE("Invalid sample rate %d used for AMRWB recording",
                    mSampleRate);
            return UNKNOWN_ERROR;
            return BAD_VALUE;
        }
    }
    if (mAudioChannels != 1) {
        LOGE("Invalid number of audio channels %d used for amr recording",
                mAudioChannels);
        return UNKNOWN_ERROR;
        return BAD_VALUE;
    }

    if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
        LOGE("Invalid audio source: %d", mAudioSource);
        return UNKNOWN_ERROR;
        return BAD_VALUE;
    }

    sp<MediaSource> audioEncoder = createAudioSource();
@@ -662,7 +678,6 @@ status_t StagefrightRecorder::startAMRRecording() {
        return UNKNOWN_ERROR;
    }

    CHECK(mOutputFd >= 0);
    mWriter = new AMRWriter(dup(mOutputFd));
    mWriter->addSource(audioEncoder);

@@ -729,50 +744,7 @@ void StagefrightRecorder::clipVideoFrameWidth() {
    }
}

void StagefrightRecorder::clipVideoFrameHeight() {
    LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
    int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
                        "enc.vid.height.min", mVideoEncoder);
    int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
                        "enc.vid.height.max", mVideoEncoder);
    if (mVideoHeight < minFrameHeight) {
        LOGW("Intended video encoding frame height (%d) is too small"
             " and will be set to (%d)", mVideoHeight, minFrameHeight);
        mVideoHeight = minFrameHeight;
    } else if (mVideoHeight > maxFrameHeight) {
        LOGW("Intended video encoding frame height (%d) is too large"
             " and will be set to (%d)", mVideoHeight, maxFrameHeight);
        mVideoHeight = maxFrameHeight;
    }
}

status_t StagefrightRecorder::startMPEG4Recording() {
    mWriter = new MPEG4Writer(dup(mOutputFd));
    int32_t totalBitRate = 0;

    // Add audio source first if it exists
    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
        sp<MediaSource> audioEncoder;
        switch(mAudioEncoder) {
            case AUDIO_ENCODER_AMR_NB:
            case AUDIO_ENCODER_AMR_WB:
            case AUDIO_ENCODER_AAC:
                audioEncoder = createAudioSource();
                break;
            default:
                LOGE("Unsupported audio encoder: %d", mAudioEncoder);
                return UNKNOWN_ERROR;
        }

        if (audioEncoder == NULL) {
            return UNKNOWN_ERROR;
        }
        totalBitRate += mAudioBitRate;
        mWriter->addSource(audioEncoder);
    }
    if (mVideoSource == VIDEO_SOURCE_DEFAULT
            || mVideoSource == VIDEO_SOURCE_CAMERA) {

status_t StagefrightRecorder::setupCameraSource() {
    clipVideoBitRate();
    clipVideoFrameRate();
    clipVideoFrameWidth();
@@ -789,7 +761,6 @@ status_t StagefrightRecorder::startMPEG4Recording() {
        mCamera->lock();
    }


    // Set the actual video recording frame size
    CameraParameters params(mCamera->getParameters());
    params.setPreviewSize(mVideoWidth, mVideoHeight);
@@ -818,10 +789,31 @@ status_t StagefrightRecorder::startMPEG4Recording() {

    CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface));
    IPCThreadState::self()->restoreCallingIdentity(token);
    return OK;
}

        sp<CameraSource> cameraSource =
            CameraSource::CreateFromCamera(mCamera);
void StagefrightRecorder::clipVideoFrameHeight() {
    LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
    int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
                        "enc.vid.height.min", mVideoEncoder);
    int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
                        "enc.vid.height.max", mVideoEncoder);
    if (mVideoHeight < minFrameHeight) {
        LOGW("Intended video encoding frame height (%d) is too small"
             " and will be set to (%d)", mVideoHeight, minFrameHeight);
        mVideoHeight = minFrameHeight;
    } else if (mVideoHeight > maxFrameHeight) {
        LOGW("Intended video encoding frame height (%d) is too large"
             " and will be set to (%d)", mVideoHeight, maxFrameHeight);
        mVideoHeight = maxFrameHeight;
    }
}

status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
    status_t err = setupCameraSource();
    if (err != OK) return err;

    sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera);
    CHECK(cameraSource != NULL);

    sp<MetaData> enc_meta = new MetaData;
@@ -863,29 +855,64 @@ status_t StagefrightRecorder::startMPEG4Recording() {
    OMXClient client;
    CHECK_EQ(client.connect(), OK);

        sp<MediaSource> encoder =
            OMXCodec::Create(
    sp<MediaSource> encoder = OMXCodec::Create(
            client.interface(), enc_meta,
            true /* createEncoder */, cameraSource);
    if (encoder == NULL) {
        return UNKNOWN_ERROR;
    }

        CHECK(mOutputFd >= 0);
        totalBitRate += mVideoBitRate;
        mWriter->addSource(encoder);
    writer->addSource(encoder);
    return OK;
}

    {
        // MPEGWriter specific handling
        MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get());
        writer->setInterleaveDuration(mInterleaveDurationUs);
status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
    sp<MediaSource> audioEncoder;
    switch(mAudioEncoder) {
        case AUDIO_ENCODER_AMR_NB:
        case AUDIO_ENCODER_AMR_WB:
        case AUDIO_ENCODER_AAC:
            audioEncoder = createAudioSource();
            break;
        default:
            LOGE("Unsupported audio encoder: %d", mAudioEncoder);
            return UNKNOWN_ERROR;
    }

    if (audioEncoder == NULL) {
        return UNKNOWN_ERROR;
    }
    writer->addSource(audioEncoder);
    return OK;
}

status_t StagefrightRecorder::startMPEG4Recording() {
    int32_t totalBitRate = 0;
    status_t err = OK;
    sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd));

    // Add audio source first if it exists
    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
        err = setupAudioEncoder(writer);
        if (err != OK) return err;
        totalBitRate += mAudioBitRate;
    }
    if (mVideoSource == VIDEO_SOURCE_DEFAULT
            || mVideoSource == VIDEO_SOURCE_CAMERA) {
        err = setupVideoEncoder(writer);
        if (err != OK) return err;
        totalBitRate += mVideoBitRate;
    }

    reinterpret_cast<MPEG4Writer *>(writer.get())->
        setInterleaveDuration(mInterleaveDurationUs);

    if (mMaxFileDurationUs != 0) {
        mWriter->setMaxFileDuration(mMaxFileDurationUs);
        writer->setMaxFileDuration(mMaxFileDurationUs);
    }
    if (mMaxFileSizeBytes != 0) {
        mWriter->setMaxFileSize(mMaxFileSizeBytes);
        writer->setMaxFileSize(mMaxFileSizeBytes);
    }
    mWriter->setListener(mListener);
    sp<MetaData> meta = new MetaData;
    meta->setInt64(kKeyTime, systemTime() / 1000);
    meta->setInt32(kKeyFileType, mOutputFormat);
@@ -897,8 +924,9 @@ status_t StagefrightRecorder::startMPEG4Recording() {
    if (mTrackEveryTimeDurationUs > 0) {
        meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
    }
    mWriter->start(meta.get());
    return OK;
    writer->setListener(mListener);
    mWriter = writer;
    return mWriter->start(meta.get());
}

status_t StagefrightRecorder::pause() {
@@ -914,7 +942,7 @@ status_t StagefrightRecorder::stop() {
    LOGV("stop");
    if (mWriter != NULL) {
        mWriter->stop();
        mWriter = NULL;
        mWriter.clear();
    }

    if (mCamera != 0) {
@@ -925,7 +953,7 @@ status_t StagefrightRecorder::stop() {
            mCamera->stopPreview();
        }
        mCamera->unlock();
        mCamera = NULL;
        mCamera.clear();
        IPCThreadState::self()->restoreCallingIdentity(token);
        mFlags = 0;
    }
+7 −1
Original line number Diff line number Diff line
@@ -97,6 +97,11 @@ private:
    status_t startAMRRecording();
    status_t startAACRecording();
    sp<MediaSource> createAudioSource();
    status_t setupCameraSource();
    status_t setupAudioEncoder(const sp<MediaWriter>& writer);
    status_t setupVideoEncoder(const sp<MediaWriter>& writer);

    // Encoding parameter handling utilities
    status_t setParameter(const String8 &key, const String8 &value);
    status_t setParamAudioEncodingBitRate(int32_t bitRate);
    status_t setParamAudioNumberOfChannels(int32_t channles);
@@ -108,7 +113,8 @@ private:
    status_t setParamTrackFrameStatus(int32_t nFrames);
    status_t setParamInterleaveDuration(int32_t durationUs);
    status_t setParam64BitFileOffset(bool use64BitFileOffset);
    status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration);
    status_t setParamMaxFileDurationUs(int64_t timeUs);
    status_t setParamMaxFileSizeBytes(int64_t bytes);
    void clipVideoBitRate();
    void clipVideoFrameRate();
    void clipVideoFrameWidth();