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

Commit bf9f408b authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Support for storing geo information in the recorded mp4/3gpp file."

parents aa126171 987ab483
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,8 @@ public:
    status_t setInterleaveDuration(uint32_t duration);
    status_t setInterleaveDuration(uint32_t duration);
    int32_t getTimeScale() const { return mTimeScale; }
    int32_t getTimeScale() const { return mTimeScale; }


    status_t setGeoData(int latitudex10000, int longitudex10000);

protected:
protected:
    virtual ~MPEG4Writer();
    virtual ~MPEG4Writer();


@@ -79,6 +81,9 @@ private:
    uint32_t mInterleaveDurationUs;
    uint32_t mInterleaveDurationUs;
    int32_t mTimeScale;
    int32_t mTimeScale;
    int64_t mStartTimestampUs;
    int64_t mStartTimestampUs;
    int mLatitudex10000;
    int mLongitudex10000;
    bool mAreGeoTagsAvailable;


    Mutex mLock;
    Mutex mLock;


@@ -169,6 +174,10 @@ private:
    void writeMvhdBox(int64_t durationUs);
    void writeMvhdBox(int64_t durationUs);
    void writeMoovBox(int64_t durationUs);
    void writeMoovBox(int64_t durationUs);
    void writeFtypBox(const MetaData *param);
    void writeFtypBox(const MetaData *param);
    void writeUdtaBox();
    void writeGeoDataBox();
    void writeLatitude(int degreex10000);
    void writeLongitude(int degreex10000);
    void sendSessionSummary();
    void sendSessionSummary();


    MPEG4Writer(const MPEG4Writer &);
    MPEG4Writer(const MPEG4Writer &);
+34 −0
Original line number Original line Diff line number Diff line
@@ -346,6 +346,40 @@ public class MediaRecorder
        setParameter("video-param-rotation-angle-degrees=" + degrees);
        setParameter("video-param-rotation-angle-degrees=" + degrees);
    }
    }


    /**
     * Store the geodata (latitude and longitude) in the output file.
     * This method should be called before prepare(). The geodata is
     * stored in udta box if the output format is OutputFormat.THREE_GPP
     * or OutputFormat.MPEG_4, and is ignored for other output formats.
     * The geodata is stored according to ISO-6709 standard.
     *
     * @param latitude latitude in degrees. Its value must be in the
     * range [-90, 90].
     * @param longitude longitude in degrees. Its value must be in the
     * range [-180, 180].
     *
     * @throws IllegalArgumentException if the given latitude or
     * longitude is out of range.
     *
     * {@hide}
     */
    public void setGeoData(float latitude, float longitude) {
        int latitudex10000  = (int) (latitude * 10000 + 0.5);
        int longitudex10000 = (int) (longitude * 10000 + 0.5);

        if (latitudex10000 > 900000 || latitudex10000 < -900000) {
            String msg = "Unsupported latitude: " + latitude;
            throw new IllegalArgumentException(msg);
        }
        if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
            String msg = "Unsupported longitude: " + longitude;
            throw new IllegalArgumentException(msg);
        }

        setParameter("param-geotag-latitude=" + latitudex10000);
        setParameter("param-geotag-longitude=" + longitudex10000);
    }

    /**
    /**
     * Sets the format of the output file produced during recording. Call this
     * Sets the format of the output file produced during recording. Call this
     * after setAudioSource()/setVideoSource() but before prepare().
     * after setAudioSource()/setVideoSource() but before prepare().
+36 −0
Original line number Original line Diff line number Diff line
@@ -593,6 +593,26 @@ status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) {
    return OK;
    return OK;
}
}


status_t StagefrightRecorder::setParamGeoDataLongitude(
    int32_t longitudex10000) {

    if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
        return BAD_VALUE;
    }
    mLongitudex10000 = longitudex10000;
    return OK;
}

status_t StagefrightRecorder::setParamGeoDataLatitude(
    int32_t latitudex10000) {

    if (latitudex10000 > 900000 || latitudex10000 < -900000) {
        return BAD_VALUE;
    }
    mLatitudex10000 = latitudex10000;
    return OK;
}

status_t StagefrightRecorder::setParameter(
status_t StagefrightRecorder::setParameter(
        const String8 &key, const String8 &value) {
        const String8 &key, const String8 &value) {
    LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
    LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -621,6 +641,16 @@ status_t StagefrightRecorder::setParameter(
        if (safe_strtoi32(value.string(), &use64BitOffset)) {
        if (safe_strtoi32(value.string(), &use64BitOffset)) {
            return setParam64BitFileOffset(use64BitOffset != 0);
            return setParam64BitFileOffset(use64BitOffset != 0);
        }
        }
    } else if (key == "param-geotag-longitude") {
        int32_t longitudex10000;
        if (safe_strtoi32(value.string(), &longitudex10000)) {
            return setParamGeoDataLongitude(longitudex10000);
        }
    } else if (key == "param-geotag-latitude") {
        int32_t latitudex10000;
        if (safe_strtoi32(value.string(), &latitudex10000)) {
            return setParamGeoDataLatitude(latitudex10000);
        }
    } else if (key == "param-track-time-status") {
    } else if (key == "param-track-time-status") {
        int64_t timeDurationUs;
        int64_t timeDurationUs;
        if (safe_strtoi64(value.string(), &timeDurationUs)) {
        if (safe_strtoi64(value.string(), &timeDurationUs)) {
@@ -1412,6 +1442,10 @@ status_t StagefrightRecorder::setupMPEG4Recording(
        reinterpret_cast<MPEG4Writer *>(writer.get())->
        reinterpret_cast<MPEG4Writer *>(writer.get())->
            setInterleaveDuration(mInterleaveDurationUs);
            setInterleaveDuration(mInterleaveDurationUs);
    }
    }
    if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
        reinterpret_cast<MPEG4Writer *>(writer.get())->
            setGeoData(mLatitudex10000, mLongitudex10000);
    }
    if (mMaxFileDurationUs != 0) {
    if (mMaxFileDurationUs != 0) {
        writer->setMaxFileDuration(mMaxFileDurationUs);
        writer->setMaxFileDuration(mMaxFileDurationUs);
    }
    }
@@ -1638,6 +1672,8 @@ status_t StagefrightRecorder::reset() {
    mIsMetaDataStoredInVideoBuffers = false;
    mIsMetaDataStoredInVideoBuffers = false;
    mEncoderProfiles = MediaProfiles::getInstance();
    mEncoderProfiles = MediaProfiles::getInstance();
    mRotationDegrees = 0;
    mRotationDegrees = 0;
    mLatitudex10000 = -3600000;
    mLongitudex10000 = -3600000;


    mOutputFd = -1;
    mOutputFd = -1;
    mOutputFdAux = -1;
    mOutputFdAux = -1;
+4 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,8 @@ private:
    int64_t mMaxFileDurationUs;
    int64_t mMaxFileDurationUs;
    int64_t mTrackEveryTimeDurationUs;
    int64_t mTrackEveryTimeDurationUs;
    int32_t mRotationDegrees;  // Clockwise
    int32_t mRotationDegrees;  // Clockwise
    int32_t mLatitudex10000;
    int32_t mLongitudex10000;


    bool mCaptureTimeLapse;
    bool mCaptureTimeLapse;
    int64_t mTimeBetweenTimeLapseFrameCaptureUs;
    int64_t mTimeBetweenTimeLapseFrameCaptureUs;
@@ -160,6 +162,8 @@ private:
    status_t setParamMaxFileDurationUs(int64_t timeUs);
    status_t setParamMaxFileDurationUs(int64_t timeUs);
    status_t setParamMaxFileSizeBytes(int64_t bytes);
    status_t setParamMaxFileSizeBytes(int64_t bytes);
    status_t setParamMovieTimeScale(int32_t timeScale);
    status_t setParamMovieTimeScale(int32_t timeScale);
    status_t setParamGeoDataLongitude(int32_t longitudex10000);
    status_t setParamGeoDataLatitude(int32_t latitudex10000);
    void clipVideoBitRate();
    void clipVideoBitRate();
    void clipVideoFrameRate();
    void clipVideoFrameRate();
    void clipVideoFrameWidth();
    void clipVideoFrameWidth();
+107 −2
Original line number Original line Diff line number Diff line
@@ -257,7 +257,10 @@ MPEG4Writer::MPEG4Writer(const char *filename)
      mOffset(0),
      mOffset(0),
      mMdatOffset(0),
      mMdatOffset(0),
      mEstimatedMoovBoxSize(0),
      mEstimatedMoovBoxSize(0),
      mInterleaveDurationUs(1000000) {
      mInterleaveDurationUs(1000000),
      mLatitudex10000(0),
      mLongitudex10000(0),
      mAreGeoTagsAvailable(false) {


    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
    if (mFd >= 0) {
    if (mFd >= 0) {
@@ -276,7 +279,10 @@ MPEG4Writer::MPEG4Writer(int fd)
      mOffset(0),
      mOffset(0),
      mMdatOffset(0),
      mMdatOffset(0),
      mEstimatedMoovBoxSize(0),
      mEstimatedMoovBoxSize(0),
      mInterleaveDurationUs(1000000) {
      mInterleaveDurationUs(1000000),
      mLatitudex10000(0),
      mLongitudex10000(0),
      mAreGeoTagsAvailable(false) {
}
}


MPEG4Writer::~MPEG4Writer() {
MPEG4Writer::~MPEG4Writer() {
@@ -724,6 +730,9 @@ void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
void MPEG4Writer::writeMoovBox(int64_t durationUs) {
void MPEG4Writer::writeMoovBox(int64_t durationUs) {
    beginBox("moov");
    beginBox("moov");
    writeMvhdBox(durationUs);
    writeMvhdBox(durationUs);
    if (mAreGeoTagsAvailable) {
        writeUdtaBox();
    }
    int32_t id = 1;
    int32_t id = 1;
    for (List<Track *>::iterator it = mTracks.begin();
    for (List<Track *>::iterator it = mTracks.begin();
        it != mTracks.end(); ++it, ++id) {
        it != mTracks.end(); ++it, ++id) {
@@ -921,6 +930,77 @@ void MPEG4Writer::writeFourcc(const char *s) {
    write(s, 1, 4);
    write(s, 1, 4);
}
}



// Written in +/-DD.DDDD format
void MPEG4Writer::writeLatitude(int degreex10000) {
    bool isNegative = (degreex10000 < 0);
    char sign = isNegative? '-': '+';

    // Handle the whole part
    char str[9];
    int wholePart = degreex10000 / 10000;
    if (wholePart == 0) {
        snprintf(str, 5, "%c%.2d.", sign, wholePart);
    } else {
        snprintf(str, 5, "%+.2d.", wholePart);
    }

    // Handle the fractional part
    int fractionalPart = degreex10000 - (wholePart * 10000);
    if (fractionalPart < 0) {
        fractionalPart = -fractionalPart;
    }
    snprintf(&str[4], 5, "%.4d", fractionalPart);

    // Do not write the null terminator
    write(str, 1, 8);
}

// Written in +/- DDD.DDDD format
void MPEG4Writer::writeLongitude(int degreex10000) {
    bool isNegative = (degreex10000 < 0);
    char sign = isNegative? '-': '+';

    // Handle the whole part
    char str[10];
    int wholePart = degreex10000 / 10000;
    if (wholePart == 0) {
        snprintf(str, 6, "%c%.3d.", sign, wholePart);
    } else {
        snprintf(str, 6, "%+.3d.", wholePart);
    }

    // Handle the fractional part
    int fractionalPart = degreex10000 - (wholePart * 10000);
    if (fractionalPart < 0) {
        fractionalPart = -fractionalPart;
    }
    snprintf(&str[5], 5, "%.4d", fractionalPart);

    // Do not write the null terminator
    write(str, 1, 9);
}

/*
 * Geodata is stored according to ISO-6709 standard.
 * latitudex10000 is latitude in degrees times 10000, and
 * longitudex10000 is longitude in degrees times 10000.
 * The range for the latitude is in [-90, +90], and
 * The range for the longitude is in [-180, +180]
 */
status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
    // Is latitude or longitude out of range?
    if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
        longitudex10000 < -1800000 || longitudex10000 > 1800000) {
        return BAD_VALUE;
    }

    mLatitudex10000 = latitudex10000;
    mLongitudex10000 = longitudex10000;
    mAreGeoTagsAvailable = true;
    return OK;
}

void MPEG4Writer::write(const void *data, size_t size) {
void MPEG4Writer::write(const void *data, size_t size) {
    write(data, 1, size);
    write(data, 1, size);
}
}
@@ -2722,4 +2802,29 @@ void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
    mOwner->endBox();  // stco or co64
    mOwner->endBox();  // stco or co64
}
}


void MPEG4Writer::writeUdtaBox() {
    beginBox("udta");
    writeGeoDataBox();
    endBox();
}

/*
 * Geodata is stored according to ISO-6709 standard.
 */
void MPEG4Writer::writeGeoDataBox() {
    beginBox("\xA9xyz");
    /*
     * For historical reasons, any user data start
     * with "\0xA9", must be followed by its assoicated
     * language code.
     * 0x0012: locale en
     * 0x15c7: language 5575
     */
    writeInt32(0x001215c7);
    writeLatitude(mLatitudex10000);
    writeLongitude(mLongitudex10000);
    writeInt8(0x2F);
    endBox();
}

}  // namespace android
}  // namespace android