summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-01-05 15:21:14 -0800
committerSteve Kondik <steve@cyngn.com>2016-01-05 15:22:11 -0800
commitde1e368d8ac5891e03e664a0ea385b896b48db0b (patch)
tree12b15ff95a32ca0a55d4fa9f94dbba8c886c09d8
parent72f2347c4eb4aa50503cd990d1ab5c0f8f5bbb61 (diff)
downloadframeworks_av-de1e368d8ac5891e03e664a0ea385b896b48db0b.zip
frameworks_av-de1e368d8ac5891e03e664a0ea385b896b48db0b.tar.gz
frameworks_av-de1e368d8ac5891e03e664a0ea385b896b48db0b.tar.bz2
stagefright: Forward-port HFR and HSR support
* CAF commit bd42a7ac3a60c0d8a079b4567484c9b006bac8ad upstream Change-Id: I457ccab603647f3139ea2199a544f64ac3d1a214
-rw-r--r--include/media/stagefright/MPEG4Writer.h3
-rw-r--r--media/libavextensions/stagefright/AVExtensions.h58
-rw-r--r--media/libavextensions/stagefright/AVUtils.cpp125
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp13
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h4
-rw-r--r--media/libstagefright/MPEG4Writer.cpp15
-rw-r--r--media/libstagefright/MediaCodecSource.cpp5
7 files changed, 213 insertions, 10 deletions
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 055c079..aeaad8f 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -186,6 +186,9 @@ private:
// To use 3gp4 box for clips with AMR audio
bool mIsAudioAMR;
+ // HFR scale
+ uint32_t mHFRRatio;
+
void lock();
void unlock();
diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h
index f14d217..968eb6d 100644
--- a/media/libavextensions/stagefright/AVExtensions.h
+++ b/media/libavextensions/stagefright/AVExtensions.h
@@ -153,7 +153,7 @@ struct AVUtils {
uint64_t /*eAacProfile*/);
virtual void extractCustomCameraKeys(
- const CameraParameters& /*params*/, sp<MetaData> &/*meta*/) {}
+ const CameraParameters& /*params*/, sp<MetaData> &/*meta*/);
virtual void printFileName(int /*fd*/) {}
virtual void addDecodingTimesFromBatch(MediaBuffer * /*buf*/,
List<int64_t> &/*decodeTimeQueue*/) {}
@@ -226,12 +226,66 @@ struct AVUtils {
int nPFrames, int nBFrames, const sp<IOMX> OMXhandle,
IOMX::node_id nodeID);
+ /*
+ * This class is a placeholder for the set of methods used
+ * to enable HFR (High Frame Rate) Recording
+ *
+ * HFR is a slow-motion recording feature where framerate
+ * is increased at capture, but file is composed to play
+ * back at normal rate, giving a net result of slow-motion.
+ * If HFR factor = N
+ * framerate (at capture and encoder) = N * actual value
+ * bitrate = N * actual value
+ * (as the encoder still gets actual timestamps)
+ * timeStamps (at composition) = actual value
+ * timeScale (at composition) = actual value / N
+ * (when parser re-generates timestamps, they will be
+ * up-scaled by factor N, which results in slow-motion)
+ *
+ * HSR is a high-framerate recording variant where timestamps
+ * are not meddled with, yielding a video mux'ed at captured
+ * fps
+ */
+ struct HFR {
+ // set kKeyHFR when 'video-hfr' paramater is enabled
+ // or set kKeyHSR when 'video-hsr' paramater is enabled
+ virtual void setHFRIfEnabled(
+ const CameraParameters& params, sp<MetaData> &meta);
+
+ // recalculate file-duration when HFR is enabled
+ virtual status_t initializeHFR(
+ const sp<MetaData> &meta, sp<AMessage> &format,
+ int64_t &maxFileDurationUs, video_encoder videoEncoder);
+
+ virtual void setHFRRatio(
+ sp<MetaData> &meta, const int32_t hfrRatio);
+
+ virtual int32_t getHFRRatio(
+ const sp<MetaData> &meta);
+
+ protected:
+ HFR() {};
+ virtual ~HFR() {};
+ friend struct AVUtils;
+
+ private:
+ // Query supported capabilities from target-specific profiles
+ virtual int32_t getHFRCapabilities(
+ video_encoder codec,
+ int& maxHFRWidth, int& maxHFRHeight, int& maxHFRFps,
+ int& maxBitrate);
+ };
+ virtual inline HFR& HFRUtils() {
+ return mHFR;
+ }
+
private:
HEVCMuxer mHEVCMuxer;
+ HFR mHFR;
// ----- NO TRESSPASSING BEYOND THIS LINE ------
DECLARE_LOADABLE_SINGLETON(AVUtils);
-};
+};
}
#endif // _AV_EXTENSIONS__H_
diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp
index 35ae36b..298434f 100644
--- a/media/libavextensions/stagefright/AVUtils.cpp
+++ b/media/libavextensions/stagefright/AVUtils.cpp
@@ -41,6 +41,7 @@
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/Utils.h>
+#include <media/MediaProfiles.h>
#if defined(QCOM_HARDWARE) || defined(FLAC_OFFLOAD_ENABLED)
#include "QCMediaDefs.h"
@@ -974,6 +975,130 @@ void AVUtils::setIntraPeriod(
return;
}
+void AVUtils::HFR::setHFRIfEnabled(
+ const CameraParameters& params,
+ sp<MetaData> &meta) {
+ const char *hfrParam = params.get("video-hfr");
+ int32_t hfr = -1;
+ if (hfrParam != NULL) {
+ hfr = atoi(hfrParam);
+ if (hfr > 0) {
+ ALOGI("Enabling HFR @ %d fps", hfr);
+ meta->setInt32(kKeyHFR, hfr);
+ return;
+ } else {
+ ALOGI("Invalid HFR rate specified : %d", hfr);
+ }
+ }
+
+ const char *hsrParam = params.get("video-hsr");
+ int32_t hsr = -1;
+ if (hsrParam != NULL ) {
+ hsr = atoi(hsrParam);
+ if (hsr > 0) {
+ ALOGI("Enabling HSR @ %d fps", hsr);
+ meta->setInt32(kKeyHSR, hsr);
+ } else {
+ ALOGI("Invalid HSR rate specified : %d", hfr);
+ }
+ }
+}
+
+status_t AVUtils::HFR::initializeHFR(
+ const sp<MetaData> &meta, sp<AMessage> &format,
+ int64_t & /*maxFileDurationUs*/, video_encoder videoEncoder) {
+ status_t retVal = OK;
+
+ int32_t hsr = 0;
+ if (meta->findInt32(kKeyHSR, &hsr) && hsr > 0) {
+ ALOGI("HSR cue found. Override encode fps to %d", hsr);
+ format->setInt32("frame-rate", hsr);
+ return retVal;
+ }
+
+ int32_t hfr = 0;
+ if (!meta->findInt32(kKeyHFR, &hfr) || (hfr <= 0)) {
+ ALOGW("Invalid HFR rate specified");
+ return retVal;
+ }
+
+ int32_t width = 0, height = 0;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ int maxW, maxH, MaxFrameRate, maxBitRate = 0;
+ if (getHFRCapabilities(videoEncoder,
+ maxW, maxH, MaxFrameRate, maxBitRate) < 0) {
+ ALOGE("Failed to query HFR target capabilities");
+ return ERROR_UNSUPPORTED;
+ }
+
+ if ((width * height * hfr) > (maxW * maxH * MaxFrameRate)) {
+ ALOGE("HFR request [%d x %d @%d fps] exceeds "
+ "[%d x %d @%d fps]. Will stay disabled",
+ width, height, hfr, maxW, maxH, MaxFrameRate);
+ return ERROR_UNSUPPORTED;
+ }
+
+ int32_t frameRate = 0, bitRate = 0;
+ CHECK(meta->findInt32(kKeyFrameRate, &frameRate));
+ CHECK(format->findInt32("bitrate", &bitRate));
+
+ if (frameRate) {
+ // scale the bitrate proportional to the hfr ratio
+ // to maintain quality, but cap it to max-supported.
+ bitRate = (hfr * bitRate) / frameRate;
+ bitRate = bitRate > maxBitRate ? maxBitRate : bitRate;
+ format->setInt32("bitrate", bitRate);
+
+ int32_t hfrRatio = hfr / frameRate;
+ format->setInt32("frame-rate", hfr);
+ format->setInt32("hfr-ratio", hfrRatio);
+ } else {
+ ALOGE("HFR: Invalid framerate");
+ return BAD_VALUE;
+ }
+
+ return retVal;
+}
+
+void AVUtils::HFR::setHFRRatio(
+ sp<MetaData> &meta, const int32_t hfrRatio) {
+ if (hfrRatio > 0) {
+ meta->setInt32(kKeyHFR, hfrRatio);
+ }
+}
+
+int32_t AVUtils::HFR::getHFRRatio(
+ const sp<MetaData> &meta) {
+ int32_t hfrRatio = 0;
+ meta->findInt32(kKeyHFR, &hfrRatio);
+ return hfrRatio ? hfrRatio : 1;
+}
+
+int32_t AVUtils::HFR::getHFRCapabilities(
+ video_encoder codec,
+ int& maxHFRWidth, int& maxHFRHeight, int& maxHFRFps,
+ int& maxBitRate) {
+ maxHFRWidth = maxHFRHeight = maxHFRFps = maxBitRate = 0;
+ MediaProfiles *profiles = MediaProfiles::getInstance();
+
+ if (profiles) {
+ maxHFRWidth = profiles->getVideoEncoderParamByName("enc.vid.hfr.width.max", codec);
+ maxHFRHeight = profiles->getVideoEncoderParamByName("enc.vid.hfr.height.max", codec);
+ maxHFRFps = profiles->getVideoEncoderParamByName("enc.vid.hfr.mode.max", codec);
+ maxBitRate = profiles->getVideoEncoderParamByName("enc.vid.bps.max", codec);
+ }
+
+ return (maxHFRWidth > 0) && (maxHFRHeight > 0) &&
+ (maxHFRFps > 0) && (maxBitRate > 0) ? 1 : -1;
+}
+
+void AVUtils::extractCustomCameraKeys(
+ const CameraParameters& params, sp<MetaData> &meta) {
+ mHFR.setHFRIfEnabled(params, meta);
+}
+
// ----- NO TRESSPASSING BEYOND THIS LINE ------
AVUtils::AVUtils() {}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 6baca4d..189bf8f 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1622,12 +1622,12 @@ status_t StagefrightRecorder::setupVideoEncoder(
}
}
- setupCustomVideoEncoderParams(cameraSource, format);
-
format->setInt32("bitrate", mVideoBitRate);
format->setInt32("frame-rate", mFrameRate);
format->setInt32("i-frame-interval", mIFramesIntervalSec);
+ setupCustomVideoEncoderParams(cameraSource, format);
+
if (mVideoTimeScale > 0) {
format->setInt32("time-scale", mVideoTimeScale);
}
@@ -2094,4 +2094,13 @@ status_t StagefrightRecorder::setSourcePause(bool pause) {
}
return err;
}
+
+void StagefrightRecorder::setupCustomVideoEncoderParams(sp<MediaSource> cameraSource,
+ sp<AMessage> &format) {
+
+ // Setup HFR if needed
+ AVUtils::get()->HFRUtils().initializeHFR(cameraSource->getFormat(), format,
+ mMaxFileDurationUs, mVideoEncoder);
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 72dc77b..d93fc3b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -154,8 +154,8 @@ protected:
status_t setupCameraSource(sp<CameraSource> *cameraSource);
status_t setupAudioEncoder(const sp<MediaWriter>& writer);
virtual status_t setupVideoEncoder(sp<MediaSource> cameraSource, sp<MediaSource> *source);
- virtual void setupCustomVideoEncoderParams(sp<MediaSource> /*cameraSource*/,
- sp<AMessage> &/*format*/) {}
+ virtual void setupCustomVideoEncoderParams(sp<MediaSource> cameraSource,
+ sp<AMessage> &format);
virtual bool setCustomVideoEncoderMime(const video_encoder videoEncoder, sp<AMessage> format);
// Encoding parameter handling utilities
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 7f7ddf7..2f1b6ac 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -321,6 +321,7 @@ private:
// Simple validation on the codec specific data
status_t checkCodecSpecificData() const;
int32_t mRotation;
+ int32_t mHFRRatio;
void updateTrackSizeEstimate();
void addOneStscTableEntry(size_t chunkId, size_t sampleId);
@@ -390,7 +391,8 @@ MPEG4Writer::MPEG4Writer(int fd)
mStartTimeOffsetMs(-1),
mMetaKeys(new AMessage()),
mIsVideoHEVC(false),
- mIsAudioAMR(false) {
+ mIsAudioAMR(false),
+ mHFRRatio(1) {
addDeviceMeta();
// Verify mFd is seekable
@@ -532,6 +534,8 @@ status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
Track *track = new Track(this, source, 1 + mTracks.size());
mTracks.push_back(track);
+ mHFRRatio = AVUtils::get()->HFRUtils().getHFRRatio(source->getFormat());
+
return OK;
}
@@ -1029,7 +1033,7 @@ void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
writeInt32(0); // version=0, flags=0
writeInt32(now); // creation time
writeInt32(now); // modification time
- writeInt32(mTimeScale); // mvhd timescale
+ writeInt32(mTimeScale / mHFRRatio); // mvhd timescale
int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
writeInt32(duration);
writeInt32(0x10000); // rate: 1.0
@@ -1477,7 +1481,8 @@ MPEG4Writer::Track::Track(
mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false),
mReachedEOS(false),
- mRotation(0) {
+ mRotation(0),
+ mHFRRatio(1) {
getCodecSpecificDataFromInputFormatIfPossible();
const char *mime;
@@ -1882,6 +1887,8 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
+ mHFRRatio = AVUtils::get()->HFRUtils().getHFRRatio(mMeta);
+
return OK;
}
@@ -3069,7 +3076,7 @@ void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
- mOwner->writeInt32(mTimeScale); // media timescale
+ mOwner->writeInt32(mTimeScale / mHFRRatio); // media timescale
int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
mOwner->writeInt32(mdhdDuration); // use media timescale
// Language follows the three letter standard ISO-639-2/T
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index aef6715..adbde54 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -429,9 +429,14 @@ status_t MediaCodecSource::initEncoder() {
return err;
}
+ int32_t hfrRatio = 0;
+ mOutputFormat->findInt32("hfr-ratio", &hfrRatio);
+
mEncoder->getOutputFormat(&mOutputFormat);
convertMessageToMetaData(mOutputFormat, mMeta);
+ AVUtils::get()->HFRUtils().setHFRRatio(mMeta, hfrRatio);
+
if (mFlags & FLAG_USE_SURFACE_INPUT) {
CHECK(mIsVideo);