summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2011-05-11 19:09:25 -0700
committerJames Dong <jdong@google.com>2011-05-13 16:29:19 -0700
commit07b1bb529a1ae76c46a71b01338c166f9490629d (patch)
tree2fff6133d9aba0bed0375fd1099edcff609c6763
parentb5212db69734962f55e1493d3e696794172ced51 (diff)
downloadframeworks_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.h9
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp36
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h4
-rw-r--r--media/libstagefright/MPEG4Writer.cpp109
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