diff options
author | James Dong <jdong@google.com> | 2011-05-11 19:09:25 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2011-05-13 16:29:19 -0700 |
commit | 07b1bb529a1ae76c46a71b01338c166f9490629d (patch) | |
tree | 2fff6133d9aba0bed0375fd1099edcff609c6763 | |
parent | b5212db69734962f55e1493d3e696794172ced51 (diff) | |
download | frameworks_av-07b1bb529a1ae76c46a71b01338c166f9490629d.zip frameworks_av-07b1bb529a1ae76c46a71b01338c166f9490629d.tar.gz frameworks_av-07b1bb529a1ae76c46a71b01338c166f9490629d.tar.bz2 |
Support for storing geo information in the recorded mp4/3gpp file.
o Geo data (latitude and longitude) is stored in udta box
Change-Id: I76e4aeb741c4b339f3753d3d28190151f3ea4919
related-to-bug: 4260295
-rw-r--r-- | include/media/stagefright/MPEG4Writer.h | 9 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 36 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 4 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 109 |
4 files changed, 156 insertions, 2 deletions
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 4b5674e..2d75728 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -55,6 +55,8 @@ public: status_t setInterleaveDuration(uint32_t duration); int32_t getTimeScale() const { return mTimeScale; } + status_t setGeoData(int latitudex10000, int longitudex10000); + protected: virtual ~MPEG4Writer(); @@ -79,6 +81,9 @@ private: uint32_t mInterleaveDurationUs; int32_t mTimeScale; int64_t mStartTimestampUs; + int mLatitudex10000; + int mLongitudex10000; + bool mAreGeoTagsAvailable; Mutex mLock; @@ -169,6 +174,10 @@ private: void writeMvhdBox(int64_t durationUs); void writeMoovBox(int64_t durationUs); void writeFtypBox(const MetaData *param); + void writeUdtaBox(); + void writeGeoDataBox(); + void writeLatitude(int degreex10000); + void writeLongitude(int degreex10000); void sendSessionSummary(); MPEG4Writer(const MPEG4Writer &); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index f21474f..9eb84d2 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -593,6 +593,26 @@ status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) { 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( const String8 &key, const String8 &value) { LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); @@ -621,6 +641,16 @@ status_t StagefrightRecorder::setParameter( if (safe_strtoi32(value.string(), &use64BitOffset)) { 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") { int64_t timeDurationUs; if (safe_strtoi64(value.string(), &timeDurationUs)) { @@ -1412,6 +1442,10 @@ status_t StagefrightRecorder::setupMPEG4Recording( reinterpret_cast<MPEG4Writer *>(writer.get())-> setInterleaveDuration(mInterleaveDurationUs); } + if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) { + reinterpret_cast<MPEG4Writer *>(writer.get())-> + setGeoData(mLatitudex10000, mLongitudex10000); + } if (mMaxFileDurationUs != 0) { writer->setMaxFileDuration(mMaxFileDurationUs); } @@ -1638,6 +1672,8 @@ status_t StagefrightRecorder::reset() { mIsMetaDataStoredInVideoBuffers = false; mEncoderProfiles = MediaProfiles::getInstance(); mRotationDegrees = 0; + mLatitudex10000 = -3600000; + mLongitudex10000 = -3600000; mOutputFd = -1; mOutputFdAux = -1; diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 15ef6e2..7795554 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -97,6 +97,8 @@ private: int64_t mMaxFileDurationUs; int64_t mTrackEveryTimeDurationUs; int32_t mRotationDegrees; // Clockwise + int32_t mLatitudex10000; + int32_t mLongitudex10000; bool mCaptureTimeLapse; int64_t mTimeBetweenTimeLapseFrameCaptureUs; @@ -160,6 +162,8 @@ private: status_t setParamMaxFileDurationUs(int64_t timeUs); status_t setParamMaxFileSizeBytes(int64_t bytes); status_t setParamMovieTimeScale(int32_t timeScale); + status_t setParamGeoDataLongitude(int32_t longitudex10000); + status_t setParamGeoDataLatitude(int32_t latitudex10000); void clipVideoBitRate(); void clipVideoFrameRate(); void clipVideoFrameWidth(); diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index fdd2f68..63878b7 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -257,7 +257,10 @@ MPEG4Writer::MPEG4Writer(const char *filename) mOffset(0), mMdatOffset(0), mEstimatedMoovBoxSize(0), - mInterleaveDurationUs(1000000) { + mInterleaveDurationUs(1000000), + mLatitudex10000(0), + mLongitudex10000(0), + mAreGeoTagsAvailable(false) { mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR); if (mFd >= 0) { @@ -276,7 +279,10 @@ MPEG4Writer::MPEG4Writer(int fd) mOffset(0), mMdatOffset(0), mEstimatedMoovBoxSize(0), - mInterleaveDurationUs(1000000) { + mInterleaveDurationUs(1000000), + mLatitudex10000(0), + mLongitudex10000(0), + mAreGeoTagsAvailable(false) { } MPEG4Writer::~MPEG4Writer() { @@ -724,6 +730,9 @@ void MPEG4Writer::writeMvhdBox(int64_t durationUs) { void MPEG4Writer::writeMoovBox(int64_t durationUs) { beginBox("moov"); writeMvhdBox(durationUs); + if (mAreGeoTagsAvailable) { + writeUdtaBox(); + } int32_t id = 1; for (List<Track *>::iterator it = mTracks.begin(); it != mTracks.end(); ++it, ++id) { @@ -921,6 +930,77 @@ void MPEG4Writer::writeFourcc(const char *s) { 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) { write(data, 1, size); } @@ -2722,4 +2802,29 @@ void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) { 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 |