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

Commit c0ab2a64 authored by James Dong's avatar James Dong
Browse files

Added encoding parameters set up for H263 video encoder

Also:
- Allowed start() call when encoder already starts and stop() call when encoder has not started yet
- Handled default value for audio/video sources/encoders and file output format

Change-Id: I03b2f7d3cf570baa0fd011a8c0ad200f2f2a5da1
parent e42b1867
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -172,6 +172,9 @@ private:
    void setVideoInputFormat(
            const char *mime, const sp<MetaData>& meta);

    status_t setupBitRate(int32_t bitRate);
    status_t setupErrorCorrectionParameters();
    status_t setupH263EncoderParameters(const sp<MetaData>& meta);
    status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta);
    status_t setupAVCEncoderParameters(const sp<MetaData>& meta);

+95 −17
Original line number Diff line number Diff line
@@ -42,11 +42,16 @@

namespace android {

StagefrightRecorder::StagefrightRecorder() {
StagefrightRecorder::StagefrightRecorder()
    : mWriter(NULL),
      mOutputFd(-1) {

    LOGV("Constructor");
    reset();
}

StagefrightRecorder::~StagefrightRecorder() {
    LOGV("Destructor");
    stop();

    if (mOutputFd >= 0) {
@@ -56,40 +61,92 @@ StagefrightRecorder::~StagefrightRecorder() {
}

status_t StagefrightRecorder::init() {
    LOGV("init");
    return OK;
}

status_t StagefrightRecorder::setAudioSource(audio_source as) {
    LOGV("setAudioSource: %d", as);
    if (as < AUDIO_SOURCE_DEFAULT ||
        as >= AUDIO_SOURCE_LIST_END) {
        return BAD_VALUE;
    }

    if (as == AUDIO_SOURCE_DEFAULT) {
        mAudioSource = AUDIO_SOURCE_MIC;
    } else {
        mAudioSource = as;
    }

    return OK;
}

status_t StagefrightRecorder::setVideoSource(video_source vs) {
    LOGV("setVideoSource: %d", vs);
    if (vs < VIDEO_SOURCE_DEFAULT ||
        vs >= VIDEO_SOURCE_LIST_END) {
        return BAD_VALUE;
    }

    if (vs == VIDEO_SOURCE_DEFAULT) {
        mVideoSource = VIDEO_SOURCE_CAMERA;
    } else {
        mVideoSource = vs;
    }

    return OK;
}

status_t StagefrightRecorder::setOutputFormat(output_format of) {
    LOGV("setOutputFormat: %d", of);
    if (of < OUTPUT_FORMAT_DEFAULT ||
        of >= OUTPUT_FORMAT_LIST_END) {
        return BAD_VALUE;
    }

    if (of == OUTPUT_FORMAT_DEFAULT) {
        mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
    } else {
        mOutputFormat = of;
    }

    return OK;
}

status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
    LOGV("setAudioEncoder: %d", ae);
    if (ae < AUDIO_ENCODER_DEFAULT ||
        ae >= AUDIO_ENCODER_LIST_END) {
        return BAD_VALUE;
    }

    if (ae == AUDIO_ENCODER_DEFAULT) {
        mAudioEncoder = AUDIO_ENCODER_AMR_NB;
    } else {
        mAudioEncoder = ae;
    }

    return OK;
}

status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
    LOGV("setVideoEncoder: %d", ve);
    if (ve < VIDEO_ENCODER_DEFAULT ||
        ve >= VIDEO_ENCODER_LIST_END) {
        return BAD_VALUE;
    }

    if (ve == VIDEO_ENCODER_DEFAULT) {
        mVideoEncoder = VIDEO_ENCODER_H263;
    } else {
        mVideoEncoder = ve;
    }

    return OK;
}

status_t StagefrightRecorder::setVideoSize(int width, int height) {
    LOGV("setVideoSize: %dx%d", width, height);
    if (width <= 0 || height <= 0) {
        LOGE("Invalid video size: %dx%d", width, height);
        return BAD_VALUE;
@@ -103,6 +160,7 @@ status_t StagefrightRecorder::setVideoSize(int width, int height) {
}

status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
    LOGV("setVideoFrameRate: %d", frames_per_second);
    if (frames_per_second <= 0 || frames_per_second > 30) {
        LOGE("Invalid video frame rate: %d", frames_per_second);
        return BAD_VALUE;
@@ -141,12 +199,14 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
}

status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
    LOGV("setPreviewSurface: %p", surface.get());
    mPreviewSurface = surface;

    return OK;
}

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

@@ -154,6 +214,7 @@ status_t StagefrightRecorder::setOutputFile(const char *path) {
}

status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
    LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
    // These don't make any sense, do they?
    CHECK_EQ(offset, 0);
    CHECK_EQ(length, 0);
@@ -720,9 +781,15 @@ status_t StagefrightRecorder::startMPEG4Recording() {
        int64_t token = IPCThreadState::self()->clearCallingIdentity();
        if (mCamera == 0) {
            mCamera = Camera::connect(mCameraId);
            if (mCamera == 0) {
                LOGE("Camera connection could not be established.");
                return -EBUSY;
            }
            mFlags &= ~FLAGS_HOT_CAMERA;
            mCamera->lock();
        }


        // Set the actual video recording frame size
        CameraParameters params(mCamera->getParameters());
        params.setPreviewSize(mVideoWidth, mVideoHeight);
@@ -835,6 +902,7 @@ status_t StagefrightRecorder::startMPEG4Recording() {
}

status_t StagefrightRecorder::pause() {
    LOGV("pause");
    if (mWriter == NULL) {
        return UNKNOWN_ERROR;
    }
@@ -843,20 +911,14 @@ status_t StagefrightRecorder::pause() {
}

status_t StagefrightRecorder::stop() {
    if (mWriter == NULL) {
        return UNKNOWN_ERROR;
    }

    LOGV("stop");
    if (mWriter != NULL) {
        mWriter->stop();
        mWriter = NULL;

    return OK;
    }

status_t StagefrightRecorder::close() {
    stop();

    if (mCamera != 0) {
        LOGV("Disconnect camera");
        int64_t token = IPCThreadState::self()->clearCallingIdentity();
        if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
            LOGV("Camera was cold when we started, stopping preview");
@@ -867,10 +929,19 @@ status_t StagefrightRecorder::close() {
        IPCThreadState::self()->restoreCallingIdentity(token);
        mFlags = 0;
    }

    return OK;
}

status_t StagefrightRecorder::close() {
    LOGV("close");
    stop();

    return OK;
}

status_t StagefrightRecorder::reset() {
    LOGV("reset");
    stop();

    // No audio or video source by default
@@ -904,6 +975,13 @@ status_t StagefrightRecorder::reset() {
}

status_t StagefrightRecorder::getMaxAmplitude(int *max) {
    LOGV("getMaxAmplitude");

    if (max == NULL) {
        LOGE("Null pointer argument");
        return BAD_VALUE;
    }

    if (mAudioSourceNode != 0) {
        *max = mAudioSourceNode->getMaxAmplitude();
    } else {
+89 −57
Original line number Diff line number Diff line
@@ -849,6 +849,7 @@ void OMXCodec::setVideoInputFormat(
        }

        case OMX_VIDEO_CodingH263:
            CHECK_EQ(setupH263EncoderParameters(meta), OK);
            break;

        case OMX_VIDEO_CodingAVC:
@@ -874,6 +875,90 @@ static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
    return ret;
}

status_t OMXCodec::setupErrorCorrectionParameters() {
    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
    InitOMXParams(&errorCorrectionType);
    errorCorrectionType.nPortIndex = kPortIndexOutput;

    status_t err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoErrorCorrection,
            &errorCorrectionType, sizeof(errorCorrectionType));
    CHECK_EQ(err, OK);

    errorCorrectionType.bEnableHEC = OMX_FALSE;
    errorCorrectionType.bEnableResync = OMX_TRUE;
    errorCorrectionType.nResynchMarkerSpacing = 256;
    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
    errorCorrectionType.bEnableRVLC = OMX_FALSE;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoErrorCorrection,
            &errorCorrectionType, sizeof(errorCorrectionType));
    CHECK_EQ(err, OK);
    return OK;
}

status_t OMXCodec::setupBitRate(int32_t bitRate) {
    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
    InitOMXParams(&bitrateType);
    bitrateType.nPortIndex = kPortIndexOutput;

    status_t err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoBitrate,
            &bitrateType, sizeof(bitrateType));
    CHECK_EQ(err, OK);

    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
    bitrateType.nTargetBitrate = bitRate;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoBitrate,
            &bitrateType, sizeof(bitrateType));
    CHECK_EQ(err, OK);
    return OK;
}

status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
    int32_t iFramesInterval, frameRate, bitRate;
    bool success = meta->findInt32(kKeyBitRate, &bitRate);
    success = success && meta->findInt32(kKeySampleRate, &frameRate);
    success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
    CHECK(success);
    OMX_VIDEO_PARAM_H263TYPE h263type;
    InitOMXParams(&h263type);
    h263type.nPortIndex = kPortIndexOutput;

    status_t err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
    CHECK_EQ(err, OK);

    h263type.nAllowedPictureTypes =
        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;

    h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
    if (h263type.nPFrames == 0) {
        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
    }
    h263type.nBFrames = 0;

    h263type.eProfile = OMX_VIDEO_H263ProfileBaseline;
    h263type.eLevel = OMX_VIDEO_H263Level45;

    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
    h263type.bForceRoundingTypeToZero = OMX_FALSE;
    h263type.nPictureHeaderRepetition = 0;
    h263type.nGOBHeaderInterval = 0;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
    CHECK_EQ(err, OK);

    CHECK_EQ(setupBitRate(bitRate), OK);
    CHECK_EQ(setupErrorCorrectionParameters(), OK);

    return OK;
}

status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
    int32_t iFramesInterval, frameRate, bitRate;
    bool success = meta->findInt32(kKeyBitRate, &bitRate);
@@ -907,53 +992,15 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
    mpeg4type.nHeaderExtension = 0;
    mpeg4type.bReversibleVLC = OMX_FALSE;

    mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
    mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
    mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
    CHECK_EQ(err, OK);

    // ----------------

    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
    InitOMXParams(&bitrateType);
    bitrateType.nPortIndex = kPortIndexOutput;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoBitrate,
            &bitrateType, sizeof(bitrateType));
    CHECK_EQ(err, OK);

    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
    bitrateType.nTargetBitrate = bitRate;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoBitrate,
            &bitrateType, sizeof(bitrateType));
    CHECK_EQ(err, OK);

    // ----------------

    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
    InitOMXParams(&errorCorrectionType);
    errorCorrectionType.nPortIndex = kPortIndexOutput;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoErrorCorrection,
            &errorCorrectionType, sizeof(errorCorrectionType));
    CHECK_EQ(err, OK);

    errorCorrectionType.bEnableHEC = OMX_FALSE;
    errorCorrectionType.bEnableResync = OMX_TRUE;
    errorCorrectionType.nResynchMarkerSpacing = 256;
    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
    errorCorrectionType.bEnableRVLC = OMX_FALSE;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoErrorCorrection,
            &errorCorrectionType, sizeof(errorCorrectionType));
    CHECK_EQ(err, OK);
    CHECK_EQ(setupBitRate(bitRate), OK);
    CHECK_EQ(setupErrorCorrectionParameters(), OK);

    return OK;
}
@@ -1004,22 +1051,7 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
    CHECK_EQ(err, OK);

    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
    InitOMXParams(&bitrateType);
    bitrateType.nPortIndex = kPortIndexOutput;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoBitrate,
            &bitrateType, sizeof(bitrateType));
    CHECK_EQ(err, OK);

    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
    bitrateType.nTargetBitrate = bitRate;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoBitrate,
            &bitrateType, sizeof(bitrateType));
    CHECK_EQ(err, OK);
    CHECK_EQ(setupBitRate(bitRate), OK);

    return OK;
}
+8 −2
Original line number Diff line number Diff line
@@ -132,7 +132,10 @@ AACEncoder::~AACEncoder() {
}

status_t AACEncoder::start(MetaData *params) {
    CHECK(!mStarted);
    if (mStarted) {
        LOGW("Call start() when encoder already started");
        return OK;
    }

    mBufferGroup = new MediaBufferGroup;
    mBufferGroup->add_buffer(new MediaBuffer(2048));
@@ -150,7 +153,10 @@ status_t AACEncoder::start(MetaData *params) {
}

status_t AACEncoder::stop() {
    CHECK(mStarted);
    if (!mStarted) {
        LOGW("Call stop() when encoder has not started");
        return OK;
    }

    if (mInputBuffer) {
        mInputBuffer->release();
+8 −2
Original line number Diff line number Diff line
@@ -70,7 +70,10 @@ static Mode PickModeFromBitrate(int32_t bps) {
}

status_t AMRNBEncoder::start(MetaData *params) {
    CHECK(!mStarted);
    if (mStarted) {
        LOGW("Call start() when encoder already started");
        return OK;
    }

    mBufferGroup = new MediaBufferGroup;
    mBufferGroup->add_buffer(new MediaBuffer(32));
@@ -97,7 +100,10 @@ status_t AMRNBEncoder::start(MetaData *params) {
}

status_t AMRNBEncoder::stop() {
    CHECK(mStarted);
    if (!mStarted) {
        LOGW("Call stop() when encoder has not started.");
        return OK;
    }

    if (mInputBuffer) {
        mInputBuffer->release();
Loading