summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/Android.mk3
-rw-r--r--media/libmedia/AudioPolicy.cpp115
-rw-r--r--media/libmedia/AudioSystem.cpp6
-rw-r--r--media/libmedia/AudioTrack.cpp14
-rw-r--r--media/libmedia/AudioTrackShared.cpp2
-rw-r--r--media/libmedia/IAudioPolicyService.cpp54
-rw-r--r--media/libmediaplayerservice/MediaPlayerFactory.cpp35
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp66
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp1
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp1
-rw-r--r--media/libstagefright/AACWriter.cpp3
-rw-r--r--media/libstagefright/ACodec.cpp26
-rw-r--r--media/libstagefright/MediaCodecList.cpp13
-rw-r--r--media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp351
-rw-r--r--media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h7
-rw-r--r--media/libstagefright/codecs/hevcdec/SoftHEVC.cpp11
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp13
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h2
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp361
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h13
-rw-r--r--media/libstagefright/codecs/on2/dec/SoftVPX.cpp11
-rw-r--r--media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp327
-rw-r--r--media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h38
-rw-r--r--media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp6
-rw-r--r--media/libstagefright/data/media_codecs_google_audio.xml3
-rw-r--r--media/libstagefright/data/media_codecs_google_video.xml2
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp4
-rw-r--r--media/libstagefright/include/SoftVideoDecoderOMXComponent.h8
-rw-r--r--media/libstagefright/include/SoftVideoEncoderOMXComponent.h38
-rw-r--r--media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp86
-rw-r--r--media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp307
-rw-r--r--media/libstagefright/tests/Utils_test.cpp7
34 files changed, 916 insertions, 1026 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index e012116..a2e0909 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -59,7 +59,8 @@ LOCAL_SRC_FILES:= \
MemoryLeakTrackUtil.cpp \
SoundPool.cpp \
SoundPoolThread.cpp \
- StringArray.cpp
+ StringArray.cpp \
+ AudioPolicy.cpp
LOCAL_SRC_FILES += ../libnbaio/roundup.c
diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp
new file mode 100644
index 0000000..d2d0971
--- /dev/null
+++ b/media/libmedia/AudioPolicy.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioPolicy"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <media/AudioPolicy.h>
+
+namespace android {
+
+//
+// AttributeMatchCriterion implementation
+//
+AttributeMatchCriterion::AttributeMatchCriterion(audio_usage_t usage,
+ audio_source_t source,
+ uint32_t rule)
+: mRule(rule)
+{
+ if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+ mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+ mAttr.mUsage = usage;
+ } else {
+ mAttr.mSource = source;
+ }
+}
+
+status_t AttributeMatchCriterion::readFromParcel(Parcel *parcel)
+{
+ mRule = parcel->readInt32();
+ if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+ mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+ mAttr.mUsage = (audio_usage_t)parcel->readInt32();
+ } else {
+ mAttr.mSource = (audio_source_t)parcel->readInt32();
+ }
+ return NO_ERROR;
+}
+
+status_t AttributeMatchCriterion::writeToParcel(Parcel *parcel) const
+{
+ parcel->writeInt32(mRule);
+ parcel->writeInt32(mAttr.mUsage);
+ return NO_ERROR;
+}
+
+//
+// AudioMix implementation
+//
+
+status_t AudioMix::readFromParcel(Parcel *parcel)
+{
+ mMixType = parcel->readInt32();
+ mFormat.sample_rate = (uint32_t)parcel->readInt32();
+ mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
+ mFormat.format = (audio_format_t)parcel->readInt32();
+ mRouteFlags = parcel->readInt32();
+ mRegistrationId = parcel->readString8();
+ size_t size = (size_t)parcel->readInt32();
+ if (size > MAX_CRITERIA_PER_MIX) {
+ size = MAX_CRITERIA_PER_MIX;
+ }
+ for (size_t i = 0; i < size; i++) {
+ AttributeMatchCriterion criterion;
+ if (criterion.readFromParcel(parcel) == NO_ERROR) {
+ mCriteria.add(criterion);
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioMix::writeToParcel(Parcel *parcel) const
+{
+ parcel->writeInt32(mMixType);
+ parcel->writeInt32(mFormat.sample_rate);
+ parcel->writeInt32(mFormat.channel_mask);
+ parcel->writeInt32(mFormat.format);
+ parcel->writeInt32(mRouteFlags);
+ parcel->writeString8(mRegistrationId);
+ size_t size = mCriteria.size();
+ if (size > MAX_CRITERIA_PER_MIX) {
+ size = MAX_CRITERIA_PER_MIX;
+ }
+ size_t sizePosition = parcel->dataPosition();
+ parcel->writeInt32(size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = parcel->dataPosition();
+ if (mCriteria[i].writeToParcel(parcel) != NO_ERROR) {
+ parcel->setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = parcel->dataPosition();
+ parcel->setDataPosition(sizePosition);
+ parcel->writeInt32(finalSize);
+ parcel->setDataPosition(position);
+ }
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 96f1ade..9cae21c 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -958,6 +958,12 @@ audio_mode_t AudioSystem::getPhoneState()
return aps->getPhoneState();
}
+status_t AudioSystem::registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->registerPolicyMixes(mixes, registration);
+}
// ---------------------------------------------------------------------------
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 4a6df6d..d9c3177 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -851,6 +851,10 @@ status_t AudioTrack::getPosition(uint32_t *position)
// due to hardware latency. We leave this behavior for now.
*position = dspFrames;
} else {
+ if (mCblk->mFlags & CBLK_INVALID) {
+ restoreTrack_l("getPosition");
+ }
+
// IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
*position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
0 : updateAndGetPosition_l();
@@ -1226,7 +1230,11 @@ status_t AudioTrack::createTrack_l()
mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
mProxy = mStaticProxy;
}
- mProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
+
+ mProxy->setVolumeLR(gain_minifloat_pack(
+ gain_from_float(mVolume[AUDIO_INTERLEAVE_LEFT]),
+ gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT])));
+
mProxy->setSendLevel(mSendLevel);
mProxy->setSampleRate(mSampleRate);
mProxy->setMinimum(mNotificationFramesAct);
@@ -1942,6 +1950,10 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
break;
}
+ if (mCblk->mFlags & CBLK_INVALID) {
+ restoreTrack_l("getTimestamp");
+ }
+
// The presented frame count must always lag behind the consumed frame count.
// To avoid a race, read the presented frames first. This ensures that presented <= consumed.
status_t status = mAudioTrack->getTimestamp(timestamp);
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 4a783b3..ff24475 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -307,6 +307,7 @@ void ClientProxy::binderDied()
{
audio_track_cblk_t* cblk = mCblk;
if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) {
+ android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
// it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process
(void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
1);
@@ -317,6 +318,7 @@ void ClientProxy::interrupt()
{
audio_track_cblk_t* cblk = mCblk;
if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) {
+ android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
(void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
1);
}
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 5873a30..70551c4 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -69,7 +69,8 @@ enum {
GET_OUTPUT_FOR_ATTR,
ACQUIRE_SOUNDTRIGGER_SESSION,
RELEASE_SOUNDTRIGGER_SESSION,
- GET_PHONE_STATE
+ GET_PHONE_STATE,
+ REGISTER_POLICY_MIXES,
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -675,6 +676,38 @@ public:
}
return (audio_mode_t)reply.readInt32();
}
+
+ virtual status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(registration ? 1 : 0);
+ size_t size = mixes.size();
+ if (size > MAX_MIXES_PER_POLICY) {
+ size = MAX_MIXES_PER_POLICY;
+ }
+ size_t sizePosition = data.dataPosition();
+ data.writeInt32(size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = data.dataPosition();
+ if (mixes[i].writeToParcel(&data) != NO_ERROR) {
+ data.setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = data.dataPosition();
+ data.setDataPosition(sizePosition);
+ data.writeInt32(finalSize);
+ data.setDataPosition(position);
+ }
+ status_t status = remote()->transact(REGISTER_POLICY_MIXES, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1147,6 +1180,25 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
} break;
+ case REGISTER_POLICY_MIXES: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ bool registration = data.readInt32() == 1;
+ Vector<AudioMix> mixes;
+ size_t size = (size_t)data.readInt32();
+ if (size > MAX_MIXES_PER_POLICY) {
+ size = MAX_MIXES_PER_POLICY;
+ }
+ for (size_t i = 0; i < size; i++) {
+ AudioMix mix;
+ if (mix.readFromParcel((Parcel*)&data) == NO_ERROR) {
+ mixes.add(mix);
+ }
+ }
+ status_t status = registerPolicyMixes(mixes, registration);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 3e0fc0d..aeefb4c 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -20,9 +20,12 @@
#include <cutils/properties.h>
#include <media/IMediaPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
#include <media/stagefright/foundation/ADebug.h>
#include <utils/Errors.h>
#include <utils/misc.h>
+#include <../libstagefright/include/WVMExtractor.h>
#include "MediaPlayerFactory.h"
@@ -179,10 +182,18 @@ class StagefrightPlayerFactory :
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
int fd,
int64_t offset,
- int64_t /*length*/,
+ int64_t length,
float /*curScore*/) {
- if (getDefaultPlayerType()
- == STAGEFRIGHT_PLAYER) {
+ if (legacyDrm()) {
+ sp<DataSource> source = new FileSource(dup(fd), offset, length);
+ String8 mimeType;
+ float confidence;
+ if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
+ return 1.0;
+ }
+ }
+
+ if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
char buf[20];
lseek(fd, offset, SEEK_SET);
read(fd, buf, sizeof(buf));
@@ -198,10 +209,28 @@ class StagefrightPlayerFactory :
return 0.0;
}
+ virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
+ const char* url,
+ float /*curScore*/) {
+ if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
+ return 1.0;
+ }
+ return 0.0;
+ }
+
virtual sp<MediaPlayerBase> createPlayer() {
ALOGV(" create StagefrightPlayer");
return new StagefrightPlayer();
}
+ private:
+ bool legacyDrm() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("persist.sys.media.legacy-drm", value, NULL)
+ && (!strcmp("1", value) || !strcasecmp("true", value))) {
+ return true;
+ }
+ return false;
+ }
};
class NuPlayerFactory : public MediaPlayerFactory::IFactory {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e7a26b6..dd79b50 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -54,6 +54,7 @@ NuPlayer::GenericSource::GenericSource(
mDurationUs(0ll),
mAudioIsVorbis(false),
mIsWidevine(false),
+ mIsSecure(false),
mUIDValid(uidValid),
mUID(uid),
mFd(-1),
@@ -163,6 +164,25 @@ status_t NuPlayer::GenericSource::initFromDataSource() {
if (mFileMeta->findInt64(kKeyDuration, &duration)) {
mDurationUs = duration;
}
+
+ if (!mIsWidevine) {
+ // Check mime to see if we actually have a widevine source.
+ // If the data source is not URL-type (eg. file source), we
+ // won't be able to tell until now.
+ const char *fileMime;
+ if (mFileMeta->findCString(kKeyMIMEType, &fileMime)
+ && !strncasecmp(fileMime, "video/wvm", 9)) {
+ mIsWidevine = true;
+ if (!mUri.empty()) {
+ // streaming, but the app forgot to specify widevine:// url
+ mWVMExtractor = static_cast<WVMExtractor *>(extractor.get());
+ mWVMExtractor->setAdaptiveStreamingMode(true);
+ if (mUIDValid) {
+ mWVMExtractor->setUID(mUID);
+ }
+ }
+ }
+ }
}
int32_t totalBitrate = 0;
@@ -208,7 +228,7 @@ status_t NuPlayer::GenericSource::initFromDataSource() {
int32_t secure;
if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
&& secure) {
- mIsWidevine = true;
+ mIsSecure = true;
if (mUIDValid) {
extractor->setUID(mUID);
}
@@ -263,7 +283,7 @@ int64_t NuPlayer::GenericSource::getLastReadPosition() {
status_t NuPlayer::GenericSource::setBuffers(
bool audio, Vector<MediaBuffer *> &buffers) {
- if (mIsWidevine && !audio) {
+ if (mIsSecure && !audio) {
return mVideoTrack.mSource->setBuffers(buffers);
}
return INVALID_OPERATION;
@@ -293,6 +313,10 @@ void NuPlayer::GenericSource::prepareAsync() {
void NuPlayer::GenericSource::onPrepareAsync() {
// delayed data source creation
if (mDataSource == NULL) {
+ // set to false first, if the extractor
+ // comes back as secure, set it to true then.
+ mIsSecure = false;
+
if (!mUri.empty()) {
const char* uri = mUri.c_str();
mIsWidevine = !strncasecmp(uri, "widevine://", 11);
@@ -312,8 +336,6 @@ void NuPlayer::GenericSource::onPrepareAsync() {
mHTTPService, uri, &mUriHeaders, &mContentType,
static_cast<HTTPBase *>(mHttpSource.get()));
} else {
- // set to false first, if the extractor
- // comes back as secure, set it to true then.
mIsWidevine = false;
mDataSource = new FileSource(mFd, mOffset, mLength);
@@ -368,7 +390,7 @@ void NuPlayer::GenericSource::onPrepareAsync() {
}
notifyFlagsChanged(
- (mIsWidevine ? FLAG_SECURE : 0)
+ (mIsSecure ? FLAG_SECURE : 0)
| FLAG_CAN_PAUSE
| FLAG_CAN_SEEK_BACKWARD
| FLAG_CAN_SEEK_FORWARD
@@ -485,8 +507,8 @@ void NuPlayer::GenericSource::stop() {
// nothing to do, just account for DRM playback status
setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
mStarted = false;
- if (mIsWidevine) {
- // For a widevine source we need to prevent any further reads.
+ if (mIsWidevine || mIsSecure) {
+ // For widevine or secure sources we need to prevent any further reads.
sp<AMessage> msg = new AMessage(kWhatStopWidevine, id());
sp<AMessage> response;
(void) msg->postAndAwaitResponse(&response);
@@ -846,7 +868,12 @@ status_t NuPlayer::GenericSource::dequeueAccessUnit(
status_t finalResult;
if (!track->mPackets->hasBufferAvailable(&finalResult)) {
- return (finalResult == OK ? -EWOULDBLOCK : finalResult);
+ if (finalResult == OK) {
+ postReadBuffer(
+ audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
+ return -EWOULDBLOCK;
+ }
+ return finalResult;
}
status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
@@ -1179,6 +1206,7 @@ status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs) {
sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
MediaBuffer* mb,
media_track_type trackType,
+ int64_t /* seekTimeUs */,
int64_t *actualTimeUs) {
bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
size_t outLength = mb->range_length();
@@ -1188,7 +1216,7 @@ sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
}
sp<ABuffer> ab;
- if (mIsWidevine && !audio) {
+ if (mIsSecure && !audio) {
// data is already provided in the buffer
ab = new ABuffer(NULL, mb->range_length());
mb->add_ref();
@@ -1216,6 +1244,16 @@ sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
meta->setInt64("timeUs", timeUs);
+#if 0
+ // Temporarily disable pre-roll till we have a full solution to handle
+ // both single seek and continous seek gracefully.
+ if (seekTimeUs > timeUs) {
+ sp<AMessage> extra = new AMessage;
+ extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
+ meta->setMessage("extra", extra);
+ }
+#endif
+
if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
const char *mime;
CHECK(mTimedTextTrack.mSource != NULL
@@ -1257,14 +1295,13 @@ void NuPlayer::GenericSource::onReadBuffer(sp<AMessage> msg) {
int32_t tmpType;
CHECK(msg->findInt32("trackType", &tmpType));
media_track_type trackType = (media_track_type)tmpType;
+ readBuffer(trackType);
{
// only protect the variable change, as readBuffer may
- // take considerable time. This may result in one extra
- // read being processed, but that is benign.
+ // take considerable time.
Mutex::Autolock _l(mReadBufferLock);
mPendingReadBufferTypes &= ~(1 << trackType);
}
- readBuffer(trackType);
}
void NuPlayer::GenericSource::readBuffer(
@@ -1317,7 +1354,7 @@ void NuPlayer::GenericSource::readBuffer(
seeking = true;
}
- if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
+ if (mIsWidevine) {
options.setNonBlocking();
}
@@ -1348,7 +1385,8 @@ void NuPlayer::GenericSource::readBuffer(
track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
}
- sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
+ sp<ABuffer> buffer = mediaBufferToABuffer(
+ mbuf, trackType, seekTimeUs, actualTimeUs);
track->mPackets->queueAccessUnit(buffer);
formatChange = false;
seeking = false;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index f2528a9..1b63a1f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -118,6 +118,7 @@ private:
int64_t mDurationUs;
bool mAudioIsVorbis;
bool mIsWidevine;
+ bool mIsSecure;
bool mUIDValid;
uid_t mUID;
sp<IMediaHTTPService> mHTTPService;
@@ -182,6 +183,7 @@ private:
sp<ABuffer> mediaBufferToABuffer(
MediaBuffer *mbuf,
media_track_type trackType,
+ int64_t seekTimeUs,
int64_t *actualTimeUs = NULL);
void postReadBuffer(media_track_type trackType);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d433a4d..a28591e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -537,7 +537,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
sp<RefBase> obj;
CHECK(msg->findObject("native-window", &obj));
- if (mSource->getFormat(false /* audio */) == NULL) {
+ if (mSource == NULL || mSource->getFormat(false /* audio */) == NULL) {
performSetSurface(static_cast<NativeWindowWrapper *>(obj.get()));
break;
}
@@ -1667,6 +1667,10 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
+ if ((flags & NuPlayer::Source::FLAG_CAN_SEEK) == 0) {
+ driver->notifyListener(
+ MEDIA_INFO, MEDIA_INFO_NOT_SEEKABLE, 0);
+ }
driver->notifyFlagsChanged(flags);
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 6ad28b5..2abd9d6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -476,6 +476,7 @@ bool NuPlayer::Decoder::handleAnOutputBuffer() {
buffer->meta()->setInt64("timeUs", timeUs);
if (flags & MediaCodec::BUFFER_FLAG_EOS) {
buffer->meta()->setInt32("eos", true);
+ notifyResumeCompleteIfNecessary();
}
// we do not expect CODECCONFIG or SYNCFRAME for decoder
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index a1e1aec..21b74ee 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -771,6 +771,7 @@ void NuPlayer::Renderer::postDrainVideoQueue() {
if (mAnchorTimeMediaUs < 0) {
setAnchorTime(mediaTimeUs, nowUs);
+ mAnchorMaxMediaUs = mediaTimeUs;
realTimeUs = nowUs;
} else {
realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 353920e..7cc9430 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -61,7 +61,8 @@ AACWriter::AACWriter(int fd)
mPaused(false),
mResumed(false),
mChannelCount(-1),
- mSampleRate(-1) {
+ mSampleRate(-1),
+ mAACProfile(OMX_AUDIO_AACObjectLC) {
}
AACWriter::~AACWriter() {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 1413635..e1b3b4d 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1158,7 +1158,7 @@ status_t ACodec::configureCodec(
}
sp<AMessage> inputFormat = new AMessage();
- sp<AMessage> outputFormat = new AMessage();
+ sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
mIsEncoder = encoder;
@@ -1303,7 +1303,21 @@ status_t ACodec::configureCodec(
return err;
}
- inputFormat->setInt32("adaptive-playback", true);
+ int32_t maxWidth = 0, maxHeight = 0;
+ if (msg->findInt32("max-width", &maxWidth) &&
+ msg->findInt32("max-height", &maxHeight)) {
+
+ err = mOMX->prepareForAdaptivePlayback(
+ mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
+ if (err != OK) {
+ ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
+ mComponentName.c_str(), err);
+ } else {
+ inputFormat->setInt32("max-width", maxWidth);
+ inputFormat->setInt32("max-height", maxHeight);
+ inputFormat->setInt32("adaptive-playback", true);
+ }
+ }
} else {
ALOGV("Configuring CPU controlled video playback.");
mTunneled = false;
@@ -1543,6 +1557,8 @@ status_t ACodec::configureCodec(
err = setMinBufferSize(kPortIndexInput, 8192); // XXX
}
+ mBaseOutputFormat = outputFormat;
+
CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
mInputFormat = inputFormat;
@@ -3533,7 +3549,7 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
}
void ACodec::sendFormatChange(const sp<AMessage> &reply) {
- sp<AMessage> notify = mNotify->dup();
+ sp<AMessage> notify = mBaseOutputFormat->dup();
notify->setInt32("what", kWhatOutputFormatChanged);
CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
@@ -4238,7 +4254,8 @@ bool ACodec::BaseState::onOMXFillBufferDone(
case RESUBMIT_BUFFERS:
{
- if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
+ if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
+ || mCodec->mPortEOS[kPortIndexOutput])) {
ALOGV("[%s] calling fillBuffer %u",
mCodec->mComponentName.c_str(), info->mBufferID);
@@ -4648,6 +4665,7 @@ void ACodec::LoadedState::stateEntered() {
mCodec->mRepeatFrameDelayUs = -1ll;
mCodec->mInputFormat.clear();
mCodec->mOutputFormat.clear();
+ mCodec->mBaseOutputFormat.clear();
if (mCodec->mShutdownInProgress) {
bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 5b8be46..cf6e937 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -62,6 +62,14 @@ static Mutex sRemoteInitMutex;
sp<IMediaCodecList> MediaCodecList::sRemoteList;
+sp<MediaCodecList::BinderDeathObserver> MediaCodecList::sBinderDeathObserver;
+
+void MediaCodecList::BinderDeathObserver::binderDied(const wp<IBinder> &who __unused) {
+ Mutex::Autolock _l(sRemoteInitMutex);
+ sRemoteList.clear();
+ sBinderDeathObserver.clear();
+}
+
// static
sp<IMediaCodecList> MediaCodecList::getInstance() {
Mutex::Autolock _l(sRemoteInitMutex);
@@ -72,8 +80,11 @@ sp<IMediaCodecList> MediaCodecList::getInstance() {
interface_cast<IMediaPlayerService>(binder);
if (service.get() != NULL) {
sRemoteList = service->getCodecList();
+ if (sRemoteList != NULL) {
+ sBinderDeathObserver = new BinderDeathObserver();
+ binder->linkToDeath(sBinderDeathObserver.get());
+ }
}
-
if (sRemoteList == NULL) {
// if failed to get remote list, create local list
sRemoteList = getLocalInstance();
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index bb55871..24dfc29 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoftAVCEncoder"
#include <utils/Log.h>
+#include <utils/misc.h>
#include "avcenc_api.h"
#include "avcenc_int.h"
@@ -25,6 +26,7 @@
#include <HardwareAPI.h>
#include <MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
@@ -51,31 +53,36 @@ static void InitOMXParams(T *params) {
params->nVersion.s.nStep = 0;
}
+static const CodecProfileLevel kProfileLevels[] = {
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 },
+};
+
typedef struct LevelConversion {
OMX_U32 omxLevel;
AVCLevel avcLevel;
+ uint32_t maxMacroBlocks;
} LevelConcersion;
static LevelConversion ConversionTable[] = {
- { OMX_VIDEO_AVCLevel1, AVC_LEVEL1_B },
- { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1 },
- { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1 },
- { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2 },
- { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3 },
- { OMX_VIDEO_AVCLevel2, AVC_LEVEL2 },
+ { OMX_VIDEO_AVCLevel1, AVC_LEVEL1_B, 99 },
+ { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1, 99 },
+ { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1, 396 },
+ { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2, 396 },
+ { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3, 396 },
+ { OMX_VIDEO_AVCLevel2, AVC_LEVEL2, 396 },
#if 0
- // encoding speed is very poor if video
- // resolution is higher than CIF
- { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1 },
- { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2 },
- { OMX_VIDEO_AVCLevel3, AVC_LEVEL3 },
- { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1 },
- { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2 },
- { OMX_VIDEO_AVCLevel4, AVC_LEVEL4 },
- { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1 },
- { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2 },
- { OMX_VIDEO_AVCLevel5, AVC_LEVEL5 },
- { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1 },
+ // encoding speed is very poor if video resolution
+ // is higher than CIF or if level is higher than 2
+ { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1, 792 },
+ { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2, 1620 },
+ { OMX_VIDEO_AVCLevel3, AVC_LEVEL3, 1620 },
+ { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1, 3600 },
+ { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2, 5120 },
+ { OMX_VIDEO_AVCLevel4, AVC_LEVEL4, 8192 },
+ { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1, 8192 },
+ { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2, 8704 },
+ { OMX_VIDEO_AVCLevel5, AVC_LEVEL5, 22080 },
+ { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1, 36864 },
#endif
};
@@ -148,13 +155,11 @@ SoftAVCEncoder::SoftAVCEncoder(
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
- : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
- mVideoWidth(176),
- mVideoHeight(144),
- mVideoFrameRate(30),
- mVideoBitRate(192000),
- mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
- mStoreMetaDataInBuffers(false),
+ : SoftVideoEncoderOMXComponent(
+ name, "video_encoder.avc", OMX_VIDEO_CodingAVC,
+ kProfileLevels, NELEM(kProfileLevels),
+ 176 /* width */, 144 /* height */,
+ callbacks, appData, component),
mIDRFrameRefreshIntervalInSec(1),
mAVCEncProfile(AVC_BASELINE),
mAVCEncLevel(AVC_LEVEL2),
@@ -168,7 +173,13 @@ SoftAVCEncoder::SoftAVCEncoder(
mInputFrameData(NULL),
mSliceGroup(NULL) {
- initPorts();
+ const size_t kOutputBufferSize =
+ 320 * ConversionTable[NELEM(ConversionTable) - 1].maxMacroBlocks;
+
+ initPorts(
+ kNumBuffers, kNumBuffers, kOutputBufferSize,
+ MEDIA_MIMETYPE_VIDEO_AVC, 2 /* minCompressionRatio */);
+
ALOGI("Construct SoftAVCEncoder");
}
@@ -230,30 +241,28 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() {
mEncParams->use_overrun_buffer = AVC_OFF;
- if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar
- || mStoreMetaDataInBuffers) {
+ if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
// Color conversion is needed.
free(mInputFrameData);
mInputFrameData =
- (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+ (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
CHECK(mInputFrameData != NULL);
}
// PV's AVC encoder requires the video dimension of multiple
- if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+ if (mWidth % 16 != 0 || mHeight % 16 != 0) {
ALOGE("Video frame size %dx%d must be a multiple of 16",
- mVideoWidth, mVideoHeight);
+ mWidth, mHeight);
return OMX_ErrorBadParameter;
}
- mEncParams->width = mVideoWidth;
- mEncParams->height = mVideoHeight;
- mEncParams->bitrate = mVideoBitRate;
- mEncParams->frame_rate = 1000 * mVideoFrameRate; // In frames/ms!
- mEncParams->CPB_size = (uint32_t) (mVideoBitRate >> 1);
+ mEncParams->width = mWidth;
+ mEncParams->height = mHeight;
+ mEncParams->bitrate = mBitrate;
+ mEncParams->frame_rate = (1000 * mFramerate) >> 16; // In frames/ms!, mFramerate is in Q16
+ mEncParams->CPB_size = (uint32_t) (mBitrate >> 1);
- int32_t nMacroBlocks = ((((mVideoWidth + 15) >> 4) << 4) *
- (((mVideoHeight + 15) >> 4) << 4)) >> 8;
+ int32_t nMacroBlocks = divUp(mWidth, 16) * divUp(mHeight, 16);
CHECK(mSliceGroup == NULL);
mSliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
CHECK(mSliceGroup != NULL);
@@ -272,7 +281,7 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() {
mEncParams->idr_period = 1; // All I frames
} else {
mEncParams->idr_period =
- (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+ (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16; // mFramerate is in Q16
}
// Set profile and level
@@ -345,71 +354,9 @@ void SoftAVCEncoder::releaseOutputBuffers() {
mOutputBuffers.clear();
}
-void SoftAVCEncoder::initPorts() {
- OMX_PARAM_PORTDEFINITIONTYPE def;
- InitOMXParams(&def);
-
- const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1;
-
- // 31584 is PV's magic number. Not sure why.
- const size_t kOutputBufferSize =
- (kInputBufferSize > 31584) ? kInputBufferSize: 31584;
-
- def.nPortIndex = 0;
- def.eDir = OMX_DirInput;
- def.nBufferCountMin = kNumBuffers;
- def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kInputBufferSize;
- def.bEnabled = OMX_TRUE;
- def.bPopulated = OMX_FALSE;
- def.eDomain = OMX_PortDomainVideo;
- def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 1;
-
- def.format.video.cMIMEType = const_cast<char *>("video/raw");
- def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
- def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
- def.format.video.xFramerate = (mVideoFrameRate << 16); // Q16 format
- def.format.video.nBitrate = mVideoBitRate;
- def.format.video.nFrameWidth = mVideoWidth;
- def.format.video.nFrameHeight = mVideoHeight;
- def.format.video.nStride = mVideoWidth;
- def.format.video.nSliceHeight = mVideoHeight;
-
- addPort(def);
-
- def.nPortIndex = 1;
- def.eDir = OMX_DirOutput;
- def.nBufferCountMin = kNumBuffers;
- def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kOutputBufferSize;
- def.bEnabled = OMX_TRUE;
- def.bPopulated = OMX_FALSE;
- def.eDomain = OMX_PortDomainVideo;
- def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
-
- def.format.video.cMIMEType = const_cast<char *>("video/avc");
- def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
- def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
- def.format.video.xFramerate = (0 << 16); // Q16 format
- def.format.video.nBitrate = mVideoBitRate;
- def.format.video.nFrameWidth = mVideoWidth;
- def.format.video.nFrameHeight = mVideoHeight;
- def.format.video.nStride = mVideoWidth;
- def.format.video.nSliceHeight = mVideoHeight;
-
- addPort(def);
-}
-
OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
OMX_INDEXTYPE index, OMX_PTR params) {
switch (index) {
- case OMX_IndexParamVideoErrorCorrection:
- {
- return OMX_ErrorNotImplemented;
- }
-
case OMX_IndexParamVideoBitrate:
{
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -420,37 +367,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
}
bitRate->eControlRate = OMX_Video_ControlRateVariable;
- bitRate->nTargetBitrate = mVideoBitRate;
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamVideoPortFormat:
- {
- OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
- (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
- if (formatParams->nPortIndex > 1) {
- return OMX_ErrorUndefined;
- }
-
- if (formatParams->nIndex > 2) {
- return OMX_ErrorNoMore;
- }
-
- if (formatParams->nPortIndex == 0) {
- formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
- if (formatParams->nIndex == 0) {
- formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
- } else if (formatParams->nIndex == 1) {
- formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
- } else {
- formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
- }
- } else {
- formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
- formatParams->eColorFormat = OMX_COLOR_FormatUnused;
- }
-
+ bitRate->nTargetBitrate = mBitrate;
return OMX_ErrorNone;
}
@@ -487,30 +404,8 @@ OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
return OMX_ErrorNone;
}
- case OMX_IndexParamVideoProfileLevelQuerySupported:
- {
- OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
- (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
-
- if (profileLevel->nPortIndex != 1) {
- return OMX_ErrorUndefined;
- }
-
- const size_t size =
- sizeof(ConversionTable) / sizeof(ConversionTable[0]);
-
- if (profileLevel->nProfileIndex >= size) {
- return OMX_ErrorNoMore;
- }
-
- profileLevel->eProfile = OMX_VIDEO_AVCProfileBaseline;
- profileLevel->eLevel = ConversionTable[profileLevel->nProfileIndex].omxLevel;
-
- return OMX_ErrorNone;
- }
-
default:
- return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
}
}
@@ -519,11 +414,6 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
int32_t indexFull = index;
switch (indexFull) {
- case OMX_IndexParamVideoErrorCorrection:
- {
- return OMX_ErrorNotImplemented;
- }
-
case OMX_IndexParamVideoBitrate:
{
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -534,109 +424,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
return OMX_ErrorUndefined;
}
- mVideoBitRate = bitRate->nTargetBitrate;
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamPortDefinition:
- {
- OMX_PARAM_PORTDEFINITIONTYPE *def =
- (OMX_PARAM_PORTDEFINITIONTYPE *)params;
- if (def->nPortIndex > 1) {
- return OMX_ErrorUndefined;
- }
-
- if (def->nPortIndex == 0) {
- if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
- (def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
- def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
- def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
- return OMX_ErrorUndefined;
- }
- } else {
- if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingAVC ||
- (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) {
- return OMX_ErrorUndefined;
- }
- }
-
- OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params);
- if (OMX_ErrorNone != err) {
- return err;
- }
-
- if (def->nPortIndex == 0) {
- mVideoWidth = def->format.video.nFrameWidth;
- mVideoHeight = def->format.video.nFrameHeight;
- mVideoFrameRate = def->format.video.xFramerate >> 16;
- mVideoColorFormat = def->format.video.eColorFormat;
-
- OMX_PARAM_PORTDEFINITIONTYPE *portDef =
- &editPortInfo(0)->mDef;
- portDef->format.video.nFrameWidth = mVideoWidth;
- portDef->format.video.nFrameHeight = mVideoHeight;
- portDef->format.video.nStride = portDef->format.video.nFrameWidth;
- portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight;
- portDef->format.video.xFramerate = def->format.video.xFramerate;
- portDef->format.video.eColorFormat =
- (OMX_COLOR_FORMATTYPE) mVideoColorFormat;
- portDef->nBufferSize =
- (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2;
- portDef = &editPortInfo(1)->mDef;
- portDef->format.video.nFrameWidth = mVideoWidth;
- portDef->format.video.nFrameHeight = mVideoHeight;
- } else {
- mVideoBitRate = def->format.video.nBitrate;
- }
-
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamStandardComponentRole:
- {
- const OMX_PARAM_COMPONENTROLETYPE *roleParams =
- (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
- if (strncmp((const char *)roleParams->cRole,
- "video_encoder.avc",
- OMX_MAX_STRINGNAME_SIZE - 1)) {
- return OMX_ErrorUndefined;
- }
-
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamVideoPortFormat:
- {
- const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
- (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
- if (formatParams->nPortIndex > 1) {
- return OMX_ErrorUndefined;
- }
-
- if (formatParams->nIndex > 2) {
- return OMX_ErrorNoMore;
- }
-
- if (formatParams->nPortIndex == 0) {
- if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused ||
- ((formatParams->nIndex == 0 &&
- formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
- (formatParams->nIndex == 1 &&
- formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
- (formatParams->nIndex == 2 &&
- formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
- return OMX_ErrorUndefined;
- }
- mVideoColorFormat = formatParams->eColorFormat;
- } else {
- if (formatParams->eCompressionFormat != OMX_VIDEO_CodingAVC ||
- formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
- return OMX_ErrorUndefined;
- }
- }
-
+ mBitrate = bitRate->nTargetBitrate;
return OMX_ErrorNone;
}
@@ -673,29 +461,8 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter(
return OMX_ErrorNone;
}
- case kStoreMetaDataExtensionIndex:
- {
- StoreMetaDataInBuffersParams *storeParams =
- (StoreMetaDataInBuffersParams*)params;
- if (storeParams->nPortIndex != 0) {
- ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
- __FUNCTION__);
- return OMX_ErrorUndefined;
- }
-
- mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
- ALOGV("StoreMetaDataInBuffers set to: %s",
- mStoreMetaDataInBuffers ? " true" : "false");
-
- if (mStoreMetaDataInBuffers) {
- mVideoColorFormat = OMX_COLOR_FormatAndroidOpaque;
- }
-
- return OMX_ErrorNone;
- }
-
default:
- return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
}
}
@@ -789,11 +556,11 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
if (inHeader->nFilledLen > 0) {
AVCFrameIO videoInput;
memset(&videoInput, 0, sizeof(videoInput));
- videoInput.height = ((mVideoHeight + 15) >> 4) << 4;
- videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4;
+ videoInput.height = align(mHeight, 16);
+ videoInput.pitch = align(mWidth, 16);
videoInput.coding_timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms
const uint8_t *inputData = NULL;
- if (mStoreMetaDataInBuffers) {
+ if (mInputDataIsMeta) {
if (inHeader->nFilledLen != 8) {
ALOGE("MetaData buffer is wrong size! "
"(got %u bytes, expected 8)", inHeader->nFilledLen);
@@ -803,9 +570,9 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
}
inputData =
extractGraphicBuffer(
- mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1,
+ mInputFrameData, (mWidth * mHeight * 3) >> 1,
inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen,
- mVideoWidth, mVideoHeight);
+ mWidth, mHeight);
if (inputData == NULL) {
ALOGE("Unable to extract gralloc buffer in metadata mode");
mSignalledError = true;
@@ -815,9 +582,9 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
// TODO: Verify/convert pixel format enum
} else {
inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset;
- if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ if (mColorFormat != OMX_COLOR_FormatYUV420Planar) {
ConvertYUV420SemiPlanarToYUV420Planar(
- inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+ inputData, mInputFrameData, mWidth, mHeight);
inputData = mInputFrameData;
}
}
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
index 130593f..f31c1f4 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
@@ -68,12 +68,6 @@ private:
int32_t mFlags;
} InputBufferInfo;
- int32_t mVideoWidth;
- int32_t mVideoHeight;
- int32_t mVideoFrameRate;
- int32_t mVideoBitRate;
- int32_t mVideoColorFormat;
- bool mStoreMetaDataInBuffers;
int32_t mIDRFrameRefreshIntervalInSec;
AVCProfile mAVCEncProfile;
AVCLevel mAVCEncLevel;
@@ -94,7 +88,6 @@ private:
Vector<MediaBuffer *> mOutputBuffers;
Vector<InputBufferInfo> mInputBufferInfoVec;
- void initPorts();
OMX_ERRORTYPE initEncParams();
OMX_ERRORTYPE initEncoder();
OMX_ERRORTYPE releaseEncoder();
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index f4cba54..cddd176 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -26,6 +26,7 @@
#include "SoftHEVC.h"
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <OMX_VideoExt.h>
@@ -75,8 +76,12 @@ SoftHEVC::SoftHEVC(
mNewWidth(mWidth),
mNewHeight(mHeight),
mChangingResolution(false) {
- initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers,
- CODEC_MIME_TYPE);
+ const size_t kMinCompressionRatio = 4 /* compressionRatio (for Level 4+) */;
+ const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
+ // INPUT_BUF_SIZE is given by HEVC codec as minimum input size
+ initPorts(
+ kNumBuffers, max(kMaxOutputBufferSize / kMinCompressionRatio, (size_t)INPUT_BUF_SIZE),
+ kNumBuffers, CODEC_MIME_TYPE, kMinCompressionRatio);
CHECK_EQ(initDecoder(), (status_t)OK);
}
@@ -644,7 +649,7 @@ void SoftHEVC::onQueueFilled(OMX_U32 portIndex) {
// The decoder should be fixed so that |u4_error_code| instead of |status| returns
// IHEVCD_UNSUPPORTED_DIMENSIONS.
bool unsupportedDimensions =
- ((IHEVCD_UNSUPPORTED_DIMENSIONS == status)
+ ((IHEVCD_UNSUPPORTED_DIMENSIONS == (IHEVCD_CXA_ERROR_CODES_T)status)
|| (IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code));
bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index e399984..ede645c 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -21,6 +21,7 @@
#include "SoftMPEG4.h"
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/IOMX.h>
@@ -70,7 +71,7 @@ SoftMPEG4::SoftMPEG4(
mPvTime(0) {
initPorts(
kNumInputBuffers,
- 8192 /* inputBufferSize */,
+ 352 * 288 * 3 / 2 /* minInputBufferSize */,
kNumOutputBuffers,
(mMode == MODE_MPEG4)
? MEDIA_MIMETYPE_VIDEO_MPEG4 : MEDIA_MIMETYPE_VIDEO_H263);
@@ -353,14 +354,14 @@ void SoftMPEG4::onReset() {
}
}
-void SoftMPEG4::updatePortDefinitions() {
- SoftVideoDecoderOMXComponent::updatePortDefinitions();
+void SoftMPEG4::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
+ SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop, updateInputSize);
/* We have to align our width and height - this should affect stride! */
OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
- def->nBufferSize =
- (((def->format.video.nFrameWidth + 15) & -16)
- * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
+ def->format.video.nStride = align(def->format.video.nStride, 16);
+ def->format.video.nSliceHeight = align(def->format.video.nSliceHeight, 16);
+ def->nBufferSize = (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
}
} // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
index 8a06a00..4114e7d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
@@ -66,7 +66,7 @@ private:
status_t initDecoder();
- virtual void updatePortDefinitions();
+ virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false);
bool handlePortSettingsChange();
DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG4);
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 400f320..fa3486c 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoftMPEG4Encoder"
#include <utils/Log.h>
+#include <utils/misc.h>
#include "mp4enc_api.h"
#include "OMX_Video.h"
@@ -24,6 +25,7 @@
#include <HardwareAPI.h>
#include <MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
@@ -46,19 +48,30 @@ static void InitOMXParams(T *params) {
params->nVersion.s.nStep = 0;
}
+static const CodecProfileLevel kMPEG4ProfileLevels[] = {
+ { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 },
+};
+
+static const CodecProfileLevel kH263ProfileLevels[] = {
+ { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
+};
+
SoftMPEG4Encoder::SoftMPEG4Encoder(
const char *name,
+ const char *componentRole,
+ OMX_VIDEO_CODINGTYPE codingType,
+ const char *mime,
+ const CodecProfileLevel *profileLevels,
+ size_t numProfileLevels,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
- : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
+ : SoftVideoEncoderOMXComponent(
+ name, componentRole, codingType,
+ profileLevels, numProfileLevels,
+ 176 /* width */, 144 /* height */,
+ callbacks, appData, component),
mEncodeMode(COMBINE_MODE_WITH_ERR_RES),
- mVideoWidth(176),
- mVideoHeight(144),
- mVideoFrameRate(30),
- mVideoBitRate(192000),
- mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
- mStoreMetaDataInBuffers(false),
mIDRFrameRefreshIntervalInSec(1),
mNumInputFrames(-1),
mStarted(false),
@@ -68,13 +81,15 @@ SoftMPEG4Encoder::SoftMPEG4Encoder(
mEncParams(new tagvideoEncOptions),
mInputFrameData(NULL) {
- if (!strcmp(name, "OMX.google.h263.encoder")) {
+ if (codingType == OMX_VIDEO_CodingH263) {
mEncodeMode = H263_MODE;
- } else {
- CHECK(!strcmp(name, "OMX.google.mpeg4.encoder"));
}
- initPorts();
+ // 256 * 1024 is a magic number for PV's encoder, not sure why
+ const size_t kOutputBufferSize = 256 * 1024;
+
+ initPorts(kNumBuffers, kNumBuffers, kOutputBufferSize, mime);
+
ALOGI("Construct SoftMPEG4Encoder");
}
@@ -98,9 +113,9 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() {
return OMX_ErrorUndefined;
}
mEncParams->encMode = mEncodeMode;
- mEncParams->encWidth[0] = mVideoWidth;
- mEncParams->encHeight[0] = mVideoHeight;
- mEncParams->encFrameRate[0] = mVideoFrameRate;
+ mEncParams->encWidth[0] = mWidth;
+ mEncParams->encHeight[0] = mHeight;
+ mEncParams->encFrameRate[0] = mFramerate >> 16; // mFramerate is in Q16 format
mEncParams->rcType = VBR_1;
mEncParams->vbvDelay = 5.0f;
@@ -111,27 +126,26 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() {
mEncParams->rvlcEnable = PV_OFF;
mEncParams->numLayers = 1;
mEncParams->timeIncRes = 1000;
- mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
+ mEncParams->tickPerSrc = ((int64_t)mEncParams->timeIncRes << 16) / mFramerate;
- mEncParams->bitRate[0] = mVideoBitRate;
+ mEncParams->bitRate[0] = mBitrate;
mEncParams->iQuant[0] = 15;
mEncParams->pQuant[0] = 12;
mEncParams->quantType[0] = 0;
mEncParams->noFrameSkipped = PV_OFF;
- if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar
- || mStoreMetaDataInBuffers) {
+ if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
// Color conversion is needed.
free(mInputFrameData);
mInputFrameData =
- (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+ (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
CHECK(mInputFrameData != NULL);
}
// PV's MPEG4 encoder requires the video dimension of multiple
- if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+ if (mWidth % 16 != 0 || mHeight % 16 != 0) {
ALOGE("Video frame size %dx%d must be a multiple of 16",
- mVideoWidth, mVideoHeight);
+ mWidth, mHeight);
return OMX_ErrorBadParameter;
}
@@ -142,7 +156,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::initEncParams() {
mEncParams->intraPeriod = 1; // All I frames
} else {
mEncParams->intraPeriod =
- (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+ (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16;
}
mEncParams->numIntraMB = 0;
@@ -201,81 +215,9 @@ OMX_ERRORTYPE SoftMPEG4Encoder::releaseEncoder() {
return OMX_ErrorNone;
}
-void SoftMPEG4Encoder::initPorts() {
- OMX_PARAM_PORTDEFINITIONTYPE def;
- InitOMXParams(&def);
-
- const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1;
-
- // 256 * 1024 is a magic number for PV's encoder, not sure why
- const size_t kOutputBufferSize =
- (kInputBufferSize > 256 * 1024)
- ? kInputBufferSize: 256 * 1024;
-
- def.nPortIndex = 0;
- def.eDir = OMX_DirInput;
- def.nBufferCountMin = kNumBuffers;
- def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kInputBufferSize;
- def.bEnabled = OMX_TRUE;
- def.bPopulated = OMX_FALSE;
- def.eDomain = OMX_PortDomainVideo;
- def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 1;
-
- def.format.video.cMIMEType = const_cast<char *>("video/raw");
-
- def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
- def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
- def.format.video.xFramerate = (mVideoFrameRate << 16); // Q16 format
- def.format.video.nBitrate = mVideoBitRate;
- def.format.video.nFrameWidth = mVideoWidth;
- def.format.video.nFrameHeight = mVideoHeight;
- def.format.video.nStride = mVideoWidth;
- def.format.video.nSliceHeight = mVideoHeight;
-
- addPort(def);
-
- def.nPortIndex = 1;
- def.eDir = OMX_DirOutput;
- def.nBufferCountMin = kNumBuffers;
- def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kOutputBufferSize;
- def.bEnabled = OMX_TRUE;
- def.bPopulated = OMX_FALSE;
- def.eDomain = OMX_PortDomainVideo;
- def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
-
- def.format.video.cMIMEType =
- (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
- ? const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4)
- : const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
-
- def.format.video.eCompressionFormat =
- (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
- ? OMX_VIDEO_CodingMPEG4
- : OMX_VIDEO_CodingH263;
-
- def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
- def.format.video.xFramerate = (0 << 16); // Q16 format
- def.format.video.nBitrate = mVideoBitRate;
- def.format.video.nFrameWidth = mVideoWidth;
- def.format.video.nFrameHeight = mVideoHeight;
- def.format.video.nStride = mVideoWidth;
- def.format.video.nSliceHeight = mVideoHeight;
-
- addPort(def);
-}
-
OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
OMX_INDEXTYPE index, OMX_PTR params) {
switch (index) {
- case OMX_IndexParamVideoErrorCorrection:
- {
- return OMX_ErrorNotImplemented;
- }
-
case OMX_IndexParamVideoBitrate:
{
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -286,41 +228,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
}
bitRate->eControlRate = OMX_Video_ControlRateVariable;
- bitRate->nTargetBitrate = mVideoBitRate;
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamVideoPortFormat:
- {
- OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
- (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
- if (formatParams->nPortIndex > 1) {
- return OMX_ErrorUndefined;
- }
-
- if (formatParams->nIndex > 2) {
- return OMX_ErrorNoMore;
- }
-
- if (formatParams->nPortIndex == 0) {
- formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
- if (formatParams->nIndex == 0) {
- formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
- } else if (formatParams->nIndex == 1) {
- formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
- } else {
- formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
- }
- } else {
- formatParams->eCompressionFormat =
- (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
- ? OMX_VIDEO_CodingMPEG4
- : OMX_VIDEO_CodingH263;
-
- formatParams->eColorFormat = OMX_COLOR_FormatUnused;
- }
-
+ bitRate->nTargetBitrate = mBitrate;
return OMX_ErrorNone;
}
@@ -369,32 +277,8 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
return OMX_ErrorNone;
}
- case OMX_IndexParamVideoProfileLevelQuerySupported:
- {
- OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
- (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
-
- if (profileLevel->nPortIndex != 1) {
- return OMX_ErrorUndefined;
- }
-
- if (profileLevel->nProfileIndex > 0) {
- return OMX_ErrorNoMore;
- }
-
- if (mEncodeMode == H263_MODE) {
- profileLevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
- profileLevel->eLevel = OMX_VIDEO_H263Level45;
- } else {
- profileLevel->eProfile = OMX_VIDEO_MPEG4ProfileCore;
- profileLevel->eLevel = OMX_VIDEO_MPEG4Level2;
- }
-
- return OMX_ErrorNone;
- }
-
default:
- return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
}
}
@@ -403,11 +287,6 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
int32_t indexFull = index;
switch (indexFull) {
- case OMX_IndexParamVideoErrorCorrection:
- {
- return OMX_ErrorNotImplemented;
- }
-
case OMX_IndexParamVideoBitrate:
{
OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -418,116 +297,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
return OMX_ErrorUndefined;
}
- mVideoBitRate = bitRate->nTargetBitrate;
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamPortDefinition:
- {
- OMX_PARAM_PORTDEFINITIONTYPE *def =
- (OMX_PARAM_PORTDEFINITIONTYPE *)params;
- if (def->nPortIndex > 1) {
- return OMX_ErrorUndefined;
- }
-
- if (def->nPortIndex == 0) {
- if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
- (def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
- def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
- def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
- return OMX_ErrorUndefined;
- }
- } else {
- if ((mEncodeMode == COMBINE_MODE_WITH_ERR_RES &&
- def->format.video.eCompressionFormat != OMX_VIDEO_CodingMPEG4) ||
- (mEncodeMode == H263_MODE &&
- def->format.video.eCompressionFormat != OMX_VIDEO_CodingH263) ||
- (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) {
- return OMX_ErrorUndefined;
- }
- }
-
- OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params);
- if (OMX_ErrorNone != err) {
- return err;
- }
-
- if (def->nPortIndex == 0) {
- mVideoWidth = def->format.video.nFrameWidth;
- mVideoHeight = def->format.video.nFrameHeight;
- mVideoFrameRate = def->format.video.xFramerate >> 16;
- mVideoColorFormat = def->format.video.eColorFormat;
-
- OMX_PARAM_PORTDEFINITIONTYPE *portDef =
- &editPortInfo(0)->mDef;
- portDef->format.video.nFrameWidth = mVideoWidth;
- portDef->format.video.nFrameHeight = mVideoHeight;
- portDef->format.video.nStride = portDef->format.video.nFrameWidth;
- portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight;
- portDef->format.video.xFramerate = def->format.video.xFramerate;
- portDef->format.video.eColorFormat =
- (OMX_COLOR_FORMATTYPE) mVideoColorFormat;
- portDef->nBufferSize =
- (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2;
- portDef = &editPortInfo(1)->mDef;
- portDef->format.video.nFrameWidth = mVideoWidth;
- portDef->format.video.nFrameHeight = mVideoHeight;
- } else {
- mVideoBitRate = def->format.video.nBitrate;
- }
-
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamStandardComponentRole:
- {
- const OMX_PARAM_COMPONENTROLETYPE *roleParams =
- (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
- if (strncmp((const char *)roleParams->cRole,
- (mEncodeMode == H263_MODE)
- ? "video_encoder.h263": "video_encoder.mpeg4",
- OMX_MAX_STRINGNAME_SIZE - 1)) {
- return OMX_ErrorUndefined;
- }
-
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamVideoPortFormat:
- {
- const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
- (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
- if (formatParams->nPortIndex > 1) {
- return OMX_ErrorUndefined;
- }
-
- if (formatParams->nIndex > 2) {
- return OMX_ErrorNoMore;
- }
-
- if (formatParams->nPortIndex == 0) {
- if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused ||
- ((formatParams->nIndex == 0 &&
- formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
- (formatParams->nIndex == 1 &&
- formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
- (formatParams->nIndex == 2 &&
- formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
- return OMX_ErrorUndefined;
- }
- mVideoColorFormat = formatParams->eColorFormat;
- } else {
- if ((mEncodeMode == H263_MODE &&
- formatParams->eCompressionFormat != OMX_VIDEO_CodingH263) ||
- (mEncodeMode == COMBINE_MODE_WITH_ERR_RES &&
- formatParams->eCompressionFormat != OMX_VIDEO_CodingMPEG4) ||
- formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
- return OMX_ErrorUndefined;
- }
- }
-
+ mBitrate = bitRate->nTargetBitrate;
return OMX_ErrorNone;
}
@@ -578,29 +348,8 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter(
return OMX_ErrorNone;
}
- case kStoreMetaDataExtensionIndex:
- {
- StoreMetaDataInBuffersParams *storeParams =
- (StoreMetaDataInBuffersParams*)params;
- if (storeParams->nPortIndex != 0) {
- ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
- __FUNCTION__);
- return OMX_ErrorUndefined;
- }
-
- mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
- ALOGV("StoreMetaDataInBuffers set to: %s",
- mStoreMetaDataInBuffers ? " true" : "false");
-
- if (mStoreMetaDataInBuffers) {
- mVideoColorFormat = OMX_COLOR_FormatAndroidOpaque;
- }
-
- return OMX_ErrorNone;
- }
-
default:
- return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
}
}
@@ -663,7 +412,7 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) {
if (inHeader->nFilledLen > 0) {
const uint8_t *inputData = NULL;
- if (mStoreMetaDataInBuffers) {
+ if (mInputDataIsMeta) {
if (inHeader->nFilledLen != 8) {
ALOGE("MetaData buffer is wrong size! "
"(got %u bytes, expected 8)", inHeader->nFilledLen);
@@ -673,9 +422,9 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) {
}
inputData =
extractGraphicBuffer(
- mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1,
+ mInputFrameData, (mWidth * mHeight * 3) >> 1,
inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen,
- mVideoWidth, mVideoHeight);
+ mWidth, mHeight);
if (inputData == NULL) {
ALOGE("Unable to extract gralloc buffer in metadata mode");
mSignalledError = true;
@@ -684,9 +433,9 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) {
}
} else {
inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset;
- if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ if (mColorFormat != OMX_COLOR_FormatYUV420Planar) {
ConvertYUV420SemiPlanarToYUV420Planar(
- inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+ inputData, mInputFrameData, mWidth, mHeight);
inputData = mInputFrameData;
}
}
@@ -696,8 +445,8 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) {
VideoEncFrameIO vin, vout;
memset(&vin, 0, sizeof(vin));
memset(&vout, 0, sizeof(vout));
- vin.height = ((mVideoHeight + 15) >> 4) << 4;
- vin.pitch = ((mVideoWidth + 15) >> 4) << 4;
+ vin.height = align(mHeight, 16);
+ vin.pitch = align(mWidth, 16);
vin.timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms
vin.yChan = (uint8_t *)inputData;
vin.uChan = vin.yChan + vin.height * vin.pitch;
@@ -745,5 +494,19 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) {
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
- return new android::SoftMPEG4Encoder(name, callbacks, appData, component);
+ using namespace android;
+ if (!strcmp(name, "OMX.google.h263.encoder")) {
+ return new android::SoftMPEG4Encoder(
+ name, "video_encoder.h263", OMX_VIDEO_CodingH263, MEDIA_MIMETYPE_VIDEO_H263,
+ kH263ProfileLevels, NELEM(kH263ProfileLevels),
+ callbacks, appData, component);
+ } else if (!strcmp(name, "OMX.google.mpeg4.encoder")) {
+ return new android::SoftMPEG4Encoder(
+ name, "video_encoder.mpeg4", OMX_VIDEO_CodingMPEG4, MEDIA_MIMETYPE_VIDEO_MPEG4,
+ kMPEG4ProfileLevels, NELEM(kMPEG4ProfileLevels),
+ callbacks, appData, component);
+ } else {
+ CHECK(!"Unknown component");
+ }
+ return NULL;
}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index b0605b4..25ecdc9 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -25,11 +25,17 @@
namespace android {
+struct CodecProfileLevel;
struct MediaBuffer;
struct SoftMPEG4Encoder : public SoftVideoEncoderOMXComponent {
SoftMPEG4Encoder(
const char *name,
+ const char *componentRole,
+ OMX_VIDEO_CODINGTYPE codingType,
+ const char *mime,
+ const CodecProfileLevel *profileLevels,
+ size_t numProfileLevels,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component);
@@ -58,12 +64,6 @@ private:
} InputBufferInfo;
MP4EncodingMode mEncodeMode;
- int32_t mVideoWidth;
- int32_t mVideoHeight;
- int32_t mVideoFrameRate;
- int32_t mVideoBitRate;
- int32_t mVideoColorFormat;
- bool mStoreMetaDataInBuffers;
int32_t mIDRFrameRefreshIntervalInSec;
int64_t mNumInputFrames;
@@ -76,7 +76,6 @@ private:
uint8_t *mInputFrameData;
Vector<InputBufferInfo> mInputBufferInfoVec;
- void initPorts();
OMX_ERRORTYPE initEncParams();
OMX_ERRORTYPE initEncoder();
OMX_ERRORTYPE releaseEncoder();
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 87d6961..8a95643 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -40,10 +40,13 @@ SoftVPX::SoftVPX(
mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9),
mCtx(NULL),
mImg(NULL) {
- initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */,
- kNumBuffers,
- codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9);
-
+ // arbitrary from avc/hevc as vpx does not specify a min compression ratio
+ const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4;
+ const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9;
+ const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
+ initPorts(
+ kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */,
+ kNumBuffers, mime, kMinCompressionRatio);
CHECK_EQ(initDecoder(), (status_t)OK);
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 0285feb..970acf3 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -19,6 +19,7 @@
#include "SoftVPXEncoder.h"
#include <utils/Log.h>
+#include <utils/misc.h>
#include <media/hardware/HardwareAPI.h>
#include <media/hardware/MetadataBufferType.h>
@@ -50,23 +51,29 @@ static int GetCPUCoreCount() {
return cpuCoreCount;
}
+static const CodecProfileLevel kProfileLevels[] = {
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 },
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 },
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 },
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 },
+};
+
SoftVPXEncoder::SoftVPXEncoder(const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
- : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
+ : SoftVideoEncoderOMXComponent(
+ name, "video_encoder.vp8", OMX_VIDEO_CodingVP8,
+ kProfileLevels, NELEM(kProfileLevels),
+ 176 /* width */, 144 /* height */,
+ callbacks, appData, component),
mCodecContext(NULL),
mCodecConfiguration(NULL),
mCodecInterface(NULL),
- mWidth(176),
- mHeight(144),
- mBitrate(192000), // in bps
- mFramerate(30 << 16), // in Q16 format
mBitrateUpdated(false),
mBitrateControlMode(VPX_VBR), // variable bitrate
mDCTPartitions(0),
mErrorResilience(OMX_FALSE),
- mColorFormat(OMX_COLOR_FormatYUV420Planar),
mLevel(OMX_VIDEO_VP8Level_Version0),
mKeyFrameInterval(0),
mMinQuantizer(0),
@@ -77,83 +84,22 @@ SoftVPXEncoder::SoftVPXEncoder(const char *name,
mTemporalPatternIdx(0),
mLastTimestamp(0x7FFFFFFFFFFFFFFFLL),
mConversionBuffer(NULL),
- mInputDataIsMeta(false),
mKeyFrameRequested(false) {
memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
mTemporalLayerBitrateRatio[0] = 100;
- initPorts();
-}
+ const size_t kMinOutputBufferSize = 1024 * 1024; // arbitrary
-SoftVPXEncoder::~SoftVPXEncoder() {
- releaseEncoder();
+ initPorts(
+ kNumBuffers, kNumBuffers, kMinOutputBufferSize,
+ MEDIA_MIMETYPE_VIDEO_VP8, 2 /* minCompressionRatio */);
}
-void SoftVPXEncoder::initPorts() {
- OMX_PARAM_PORTDEFINITIONTYPE inputPort;
- OMX_PARAM_PORTDEFINITIONTYPE outputPort;
-
- InitOMXParams(&inputPort);
- InitOMXParams(&outputPort);
-
- inputPort.nBufferCountMin = kNumBuffers;
- inputPort.nBufferCountActual = inputPort.nBufferCountMin;
- inputPort.bEnabled = OMX_TRUE;
- inputPort.bPopulated = OMX_FALSE;
- inputPort.eDomain = OMX_PortDomainVideo;
- inputPort.bBuffersContiguous = OMX_FALSE;
- inputPort.format.video.pNativeRender = NULL;
- inputPort.format.video.nFrameWidth = mWidth;
- inputPort.format.video.nFrameHeight = mHeight;
- inputPort.format.video.nStride = inputPort.format.video.nFrameWidth;
- inputPort.format.video.nSliceHeight = inputPort.format.video.nFrameHeight;
- inputPort.format.video.nBitrate = 0;
- // frameRate is in Q16 format.
- inputPort.format.video.xFramerate = mFramerate;
- inputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
- inputPort.nPortIndex = kInputPortIndex;
- inputPort.eDir = OMX_DirInput;
- inputPort.nBufferAlignment = kInputBufferAlignment;
- inputPort.format.video.cMIMEType =
- const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
- inputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
- inputPort.format.video.eColorFormat = mColorFormat;
- inputPort.format.video.pNativeWindow = NULL;
- inputPort.nBufferSize =
- (inputPort.format.video.nStride *
- inputPort.format.video.nSliceHeight * 3) / 2;
-
- addPort(inputPort);
-
- outputPort.nBufferCountMin = kNumBuffers;
- outputPort.nBufferCountActual = outputPort.nBufferCountMin;
- outputPort.bEnabled = OMX_TRUE;
- outputPort.bPopulated = OMX_FALSE;
- outputPort.eDomain = OMX_PortDomainVideo;
- outputPort.bBuffersContiguous = OMX_FALSE;
- outputPort.format.video.pNativeRender = NULL;
- outputPort.format.video.nFrameWidth = mWidth;
- outputPort.format.video.nFrameHeight = mHeight;
- outputPort.format.video.nStride = outputPort.format.video.nFrameWidth;
- outputPort.format.video.nSliceHeight = outputPort.format.video.nFrameHeight;
- outputPort.format.video.nBitrate = mBitrate;
- outputPort.format.video.xFramerate = 0;
- outputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
- outputPort.nPortIndex = kOutputPortIndex;
- outputPort.eDir = OMX_DirOutput;
- outputPort.nBufferAlignment = kOutputBufferAlignment;
- outputPort.format.video.cMIMEType =
- const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP8);
- outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
- outputPort.format.video.eColorFormat = OMX_COLOR_FormatUnused;
- outputPort.format.video.pNativeWindow = NULL;
- outputPort.nBufferSize = 1024 * 1024; // arbitrary
-
- addPort(outputPort);
+SoftVPXEncoder::~SoftVPXEncoder() {
+ releaseEncoder();
}
-
status_t SoftVPXEncoder::initEncoder() {
vpx_codec_err_t codec_return;
@@ -409,38 +355,6 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
const int32_t indexFull = index;
switch (indexFull) {
- case OMX_IndexParamVideoPortFormat: {
- OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
- (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
-
- if (formatParams->nPortIndex == kInputPortIndex) {
- if (formatParams->nIndex >= kNumberOfSupportedColorFormats) {
- return OMX_ErrorNoMore;
- }
-
- // Color formats, in order of preference
- if (formatParams->nIndex == 0) {
- formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
- } else if (formatParams->nIndex == 1) {
- formatParams->eColorFormat =
- OMX_COLOR_FormatYUV420SemiPlanar;
- } else {
- formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
- }
-
- formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
- formatParams->xFramerate = mFramerate;
- return OMX_ErrorNone;
- } else if (formatParams->nPortIndex == kOutputPortIndex) {
- formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8;
- formatParams->eColorFormat = OMX_COLOR_FormatUnused;
- formatParams->xFramerate = 0;
- return OMX_ErrorNone;
- } else {
- return OMX_ErrorBadPortIndex;
- }
- }
-
case OMX_IndexParamVideoBitrate: {
OMX_VIDEO_PARAM_BITRATETYPE *bitrate =
(OMX_VIDEO_PARAM_BITRATETYPE *)param;
@@ -495,54 +409,8 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
return OMX_ErrorNone;
}
- case OMX_IndexParamVideoProfileLevelQuerySupported: {
- OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
- (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
-
- if (profileAndLevel->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
-
- switch (profileAndLevel->nProfileIndex) {
- case 0:
- profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version0;
- break;
-
- case 1:
- profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version1;
- break;
-
- case 2:
- profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version2;
- break;
-
- case 3:
- profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version3;
- break;
-
- default:
- return OMX_ErrorNoMore;
- }
-
- profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamVideoProfileLevelCurrent: {
- OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
- (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
-
- if (profileAndLevel->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
-
- profileAndLevel->eLevel = mLevel;
- profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
- return OMX_ErrorNone;
- }
-
default:
- return SimpleSoftOMXComponent::internalGetParameter(index, param);
+ return SoftVideoEncoderOMXComponent::internalGetParameter(index, param);
}
}
@@ -553,30 +421,10 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
const int32_t indexFull = index;
switch (indexFull) {
- case OMX_IndexParamStandardComponentRole:
- return internalSetRoleParams(
- (const OMX_PARAM_COMPONENTROLETYPE *)param);
-
case OMX_IndexParamVideoBitrate:
return internalSetBitrateParams(
(const OMX_VIDEO_PARAM_BITRATETYPE *)param);
- case OMX_IndexParamPortDefinition:
- {
- OMX_ERRORTYPE err = internalSetPortParams(
- (const OMX_PARAM_PORTDEFINITIONTYPE *)param);
-
- if (err != OMX_ErrorNone) {
- return err;
- }
-
- return SimpleSoftOMXComponent::internalSetParameter(index, param);
- }
-
- case OMX_IndexParamVideoPortFormat:
- return internalSetFormatParams(
- (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param);
-
case OMX_IndexParamVideoVp8:
return internalSetVp8Params(
(const OMX_VIDEO_PARAM_VP8TYPE *)param);
@@ -585,27 +433,8 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
return internalSetAndroidVp8Params(
(const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
- case OMX_IndexParamVideoProfileLevelCurrent:
- return internalSetProfileLevel(
- (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param);
-
- case kStoreMetaDataExtensionIndex:
- {
- // storeMetaDataInBuffers
- const StoreMetaDataInBuffersParams *storeParam =
- (const StoreMetaDataInBuffersParams *)param;
-
- if (storeParam->nPortIndex != kInputPortIndex) {
- return OMX_ErrorBadPortIndex;
- }
-
- mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
-
- return OMX_ErrorNone;
- }
-
default:
- return SimpleSoftOMXComponent::internalSetParameter(index, param);
+ return SoftVideoEncoderOMXComponent::internalSetParameter(index, param);
}
}
@@ -646,29 +475,6 @@ OMX_ERRORTYPE SoftVPXEncoder::setConfig(
}
}
-OMX_ERRORTYPE SoftVPXEncoder::internalSetProfileLevel(
- const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel) {
- if (profileAndLevel->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
-
- if (profileAndLevel->eProfile != OMX_VIDEO_VP8ProfileMain) {
- return OMX_ErrorBadParameter;
- }
-
- if (profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version0 ||
- profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version1 ||
- profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version2 ||
- profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version3) {
- mLevel = (OMX_VIDEO_VP8LEVELTYPE)profileAndLevel->eLevel;
- } else {
- return OMX_ErrorBadParameter;
- }
-
- return OMX_ErrorNone;
-}
-
-
OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params(
const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
if (vp8Params->nPortIndex != kOutputPortIndex) {
@@ -743,95 +549,6 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params(
return OMX_ErrorNone;
}
-OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
- const OMX_VIDEO_PARAM_PORTFORMATTYPE* format) {
- if (format->nPortIndex == kInputPortIndex) {
- if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
- format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
- format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
- mColorFormat = format->eColorFormat;
-
- OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
- def->format.video.eColorFormat = mColorFormat;
-
- return OMX_ErrorNone;
- } else {
- ALOGE("Unsupported color format %i", format->eColorFormat);
- return OMX_ErrorUnsupportedSetting;
- }
- } else if (format->nPortIndex == kOutputPortIndex) {
- if (format->eCompressionFormat == OMX_VIDEO_CodingVP8) {
- return OMX_ErrorNone;
- } else {
- return OMX_ErrorUnsupportedSetting;
- }
- } else {
- return OMX_ErrorBadPortIndex;
- }
-}
-
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetRoleParams(
- const OMX_PARAM_COMPONENTROLETYPE* role) {
- const char* roleText = (const char*)role->cRole;
- const size_t roleTextMaxSize = OMX_MAX_STRINGNAME_SIZE - 1;
-
- if (strncmp(roleText, "video_encoder.vp8", roleTextMaxSize)) {
- ALOGE("Unsupported component role");
- return OMX_ErrorBadParameter;
- }
-
- return OMX_ErrorNone;
-}
-
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams(
- const OMX_PARAM_PORTDEFINITIONTYPE* port) {
- if (port->nPortIndex == kInputPortIndex) {
- mWidth = port->format.video.nFrameWidth;
- mHeight = port->format.video.nFrameHeight;
-
- // xFramerate comes in Q16 format, in frames per second unit
- mFramerate = port->format.video.xFramerate;
-
- if (port->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar ||
- port->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
- port->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
- mColorFormat = port->format.video.eColorFormat;
- } else {
- return OMX_ErrorUnsupportedSetting;
- }
-
- OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
- def->format.video.nFrameWidth = mWidth;
- def->format.video.nFrameHeight = mHeight;
- def->format.video.nStride = def->format.video.nFrameWidth;
- def->format.video.nSliceHeight = def->format.video.nFrameHeight;
- def->format.video.xFramerate = mFramerate;
- def->format.video.eColorFormat = mColorFormat;
- def->nBufferSize =
- (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
- def = &editPortInfo(kOutputPortIndex)->mDef;
- def->format.video.nFrameWidth = mWidth;
- def->format.video.nFrameHeight = mHeight;
-
- return OMX_ErrorNone;
- } else if (port->nPortIndex == kOutputPortIndex) {
- mBitrate = port->format.video.nBitrate;
- mWidth = port->format.video.nFrameWidth;
- mHeight = port->format.video.nFrameHeight;
-
- OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
- def->format.video.nFrameWidth = mWidth;
- def->format.video.nFrameHeight = mHeight;
- def->format.video.nBitrate = mBitrate;
- return OMX_ErrorNone;
- } else {
- return OMX_ErrorBadPortIndex;
- }
-}
-
-
OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams(
const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
if (bitrate->nPortIndex != kOutputPortIndex) {
@@ -920,7 +637,7 @@ vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() {
return flags;
}
-void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
+void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
// Initialize encoder if not already
if (mCodecContext == NULL) {
if (OK != initEncoder()) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index f4c1564..cd0a0cf 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -155,18 +155,6 @@ private:
// that specifies algorithm interface (e.g. vp8)
vpx_codec_iface_t* mCodecInterface;
- // Width of the input frames
- int32_t mWidth;
-
- // Height of the input frames
- int32_t mHeight;
-
- // Target bitrate set for the encoder, in bits per second.
- uint32_t mBitrate;
-
- // Target framerate set for the encoder.
- uint32_t mFramerate;
-
// If a request for a change it bitrate has been received.
bool mBitrateUpdated;
@@ -182,9 +170,6 @@ private:
// is enabled in encoder
OMX_BOOL mErrorResilience;
- // Color format for the input port
- OMX_COLOR_FORMATTYPE mColorFormat;
-
// Encoder profile corresponding to OMX level parameter
//
// The inconsistency in the naming is caused by
@@ -229,14 +214,8 @@ private:
// indeed YUV420SemiPlanar.
uint8_t* mConversionBuffer;
- bool mInputDataIsMeta;
-
bool mKeyFrameRequested;
- // Initializes input and output OMX ports with sensible
- // default values.
- void initPorts();
-
// Initializes vpx encoder with available settings.
status_t initEncoder();
@@ -250,23 +229,10 @@ private:
// Get current encode flags
vpx_enc_frame_flags_t getEncodeFlags();
- // Handles port changes with respect to color formats
- OMX_ERRORTYPE internalSetFormatParams(
- const OMX_VIDEO_PARAM_PORTFORMATTYPE* format);
-
- // Verifies the component role tried to be set to this OMX component is
- // strictly video_encoder.vp8
- OMX_ERRORTYPE internalSetRoleParams(
- const OMX_PARAM_COMPONENTROLETYPE* role);
-
// Updates bitrate to reflect port settings.
OMX_ERRORTYPE internalSetBitrateParams(
const OMX_VIDEO_PARAM_BITRATETYPE* bitrate);
- // Handles port definition changes.
- OMX_ERRORTYPE internalSetPortParams(
- const OMX_PARAM_PORTDEFINITIONTYPE* port);
-
// Handles vp8 specific parameters.
OMX_ERRORTYPE internalSetVp8Params(
const OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
@@ -275,10 +241,6 @@ private:
OMX_ERRORTYPE internalSetAndroidVp8Params(
const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams);
- // Updates encoder profile
- OMX_ERRORTYPE internalSetProfileLevel(
- const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel);
-
DISALLOW_EVIL_CONSTRUCTORS(SoftVPXEncoder);
};
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 168208f..6b8b395 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -64,9 +64,11 @@ SoftAVC::SoftAVC(
mHeadersDecoded(false),
mEOSStatus(INPUT_DATA_AVAILABLE),
mSignalledError(false) {
+ const size_t kMinCompressionRatio = 2;
+ const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
initPorts(
- kNumInputBuffers, 8192 /* inputBufferSize */,
- kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC);
+ kNumInputBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* minInputBufferSize */,
+ kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC, kMinCompressionRatio);
CHECK_EQ(initDecoder(), (status_t)OK);
}
diff --git a/media/libstagefright/data/media_codecs_google_audio.xml b/media/libstagefright/data/media_codecs_google_audio.xml
index 85f6615..a06684b 100644
--- a/media/libstagefright/data/media_codecs_google_audio.xml
+++ b/media/libstagefright/data/media_codecs_google_audio.xml
@@ -65,7 +65,8 @@
<Encoders>
<MediaCodec name="OMX.google.aac.encoder" type="audio/mp4a-latm">
<Limit name="channel-count" max="6" />
- <Limit name="sample-rate" ranges="11025,12000,16000,22050,24000,32000,44100,48000" />
+ <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
+ <!-- also may support 64000, 88200 and 96000 Hz -->
<Limit name="bitrate" range="8000-960000" />
</MediaCodec>
<MediaCodec name="OMX.google.amrnb.encoder" type="audio/3gpp">
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index 1cbef39..7e9fa18 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -73,7 +73,7 @@
<Encoders>
<MediaCodec name="OMX.google.h263.encoder" type="video/3gpp">
<!-- profiles and levels: ProfileBaseline : Level45 -->
- <Limit name="size" min="16x16" max="176x144" />
+ <Limit name="size" min="176x144" max="176x144" />
<Limit name="alignment" value="16x16" />
<Limit name="bitrate" range="1-128000" />
</MediaCodec>
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 5eb4652..0b18666 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -1109,11 +1109,11 @@ status_t LiveSession::onSeek(const sp<AMessage> &msg) {
}
status_t LiveSession::getDuration(int64_t *durationUs) const {
- int64_t maxDurationUs = 0ll;
+ int64_t maxDurationUs = -1ll;
for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
- if (fetcherDurationUs >= 0ll && fetcherDurationUs > maxDurationUs) {
+ if (fetcherDurationUs > maxDurationUs) {
maxDurationUs = fetcherDurationUs;
}
}
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index 9e97ebd..4529007 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -61,9 +61,10 @@ protected:
void initPorts(OMX_U32 numInputBuffers,
OMX_U32 inputBufferSize,
OMX_U32 numOutputBuffers,
- const char *mimeType);
+ const char *mimeType,
+ OMX_U32 minCompressionRatio = 1u);
- virtual void updatePortDefinitions(bool updateCrop = true);
+ virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false);
uint32_t outputBufferWidth();
uint32_t outputBufferHeight();
@@ -99,6 +100,9 @@ protected:
} mOutputPortSettingsChange;
private:
+ uint32_t mMinInputBufferSize;
+ uint32_t mMinCompressionRatio;
+
const char *mComponentRole;
OMX_VIDEO_CODINGTYPE mCodingType;
const CodecProfileLevel *mProfileLevels;
diff --git a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
index b3b810d..b43635d 100644
--- a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
@@ -18,6 +18,8 @@
#define SOFT_VIDEO_ENCODER_OMX_COMPONENT_H_
+#include <media/IOMX.h>
+
#include "SimpleSoftOMXComponent.h"
#include <system/window.h>
@@ -28,11 +30,26 @@ namespace android {
struct SoftVideoEncoderOMXComponent : public SimpleSoftOMXComponent {
SoftVideoEncoderOMXComponent(
const char *name,
+ const char *componentRole,
+ OMX_VIDEO_CODINGTYPE codingType,
+ const CodecProfileLevel *profileLevels,
+ size_t numProfileLevels,
+ int32_t width,
+ int32_t height,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component);
+ virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR param);
+ virtual OMX_ERRORTYPE internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params);
+
protected:
+ void initPorts(
+ OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
+ const char *mime, OMX_U32 minCompressionRatio = 1);
+
+ static void setRawVideoSize(OMX_PARAM_PORTDEFINITIONTYPE *def);
+
static void ConvertFlexYUVToPlanar(
uint8_t *dst, size_t dstStride, size_t dstVStride,
struct android_ycbcr *ycbcr, int32_t width, int32_t height);
@@ -56,9 +73,30 @@ protected:
kOutputPortIndex = 1,
};
+ bool mInputDataIsMeta;
+ int32_t mWidth; // width of the input frames
+ int32_t mHeight; // height of the input frames
+ uint32_t mBitrate; // target bitrate set for the encoder, in bits per second
+ uint32_t mFramerate; // target framerate set for the encoder, in Q16 format
+ OMX_COLOR_FORMATTYPE mColorFormat; // Color format for the input port
+
private:
+ void updatePortParams();
+ OMX_ERRORTYPE internalSetPortParams(const OMX_PARAM_PORTDEFINITIONTYPE* port);
+
+ static const uint32_t kInputBufferAlignment = 1;
+ static const uint32_t kOutputBufferAlignment = 2;
+
mutable const hw_module_t *mGrallocModule;
+ uint32_t mMinOutputBufferSize;
+ uint32_t mMinCompressionRatio;
+
+ const char *mComponentRole;
+ OMX_VIDEO_CODINGTYPE mCodingType;
+ const CodecProfileLevel *mProfileLevels;
+ size_t mNumProfileLevels;
+
DISALLOW_EVIL_CONSTRUCTORS(SoftVideoEncoderOMXComponent);
};
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 2f83610..532cf2f 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -26,6 +26,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
namespace android {
@@ -61,6 +62,8 @@ SoftVideoDecoderOMXComponent::SoftVideoDecoderOMXComponent(
mCropWidth(width),
mCropHeight(height),
mOutputPortSettingsChange(NONE),
+ mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock
+ mMinCompressionRatio(1), // max input size is normally the output size
mComponentRole(componentRole),
mCodingType(codingType),
mProfileLevels(profileLevels),
@@ -71,7 +74,11 @@ void SoftVideoDecoderOMXComponent::initPorts(
OMX_U32 numInputBuffers,
OMX_U32 inputBufferSize,
OMX_U32 numOutputBuffers,
- const char *mimeType) {
+ const char *mimeType,
+ OMX_U32 minCompressionRatio) {
+ mMinInputBufferSize = inputBufferSize;
+ mMinCompressionRatio = minCompressionRatio;
+
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
@@ -120,27 +127,30 @@ void SoftVideoDecoderOMXComponent::initPorts(
addPort(def);
- updatePortDefinitions();
+ updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
}
-void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop) {
- OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
- def->format.video.nFrameWidth = mWidth;
- def->format.video.nFrameHeight = mHeight;
- def->format.video.nStride = def->format.video.nFrameWidth;
- def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-
- def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
-
- def = &editPortInfo(kOutputPortIndex)->mDef;
- def->format.video.nFrameWidth = outputBufferWidth();
- def->format.video.nFrameHeight = outputBufferHeight();
- def->format.video.nStride = def->format.video.nFrameWidth;
- def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-
- def->nBufferSize =
- (def->format.video.nFrameWidth *
- def->format.video.nFrameHeight * 3) / 2;
+void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
+ OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
+ outDef->format.video.nFrameWidth = outputBufferWidth();
+ outDef->format.video.nFrameHeight = outputBufferHeight();
+ outDef->format.video.nStride = outDef->format.video.nFrameWidth;
+ outDef->format.video.nSliceHeight = outDef->format.video.nFrameHeight;
+
+ outDef->nBufferSize =
+ (outDef->format.video.nStride * outDef->format.video.nSliceHeight * 3) / 2;
+
+ OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+ inDef->format.video.nFrameWidth = mWidth;
+ inDef->format.video.nFrameHeight = mHeight;
+ // input port is compressed, hence it has no stride
+ inDef->format.video.nStride = 0;
+ inDef->format.video.nSliceHeight = 0;
+
+ // when output format changes, input buffer size does not actually change
+ if (updateInputSize) {
+ inDef->nBufferSize = max(outDef->nBufferSize / mMinCompressionRatio, mMinInputBufferSize);
+ }
if (updateCrop) {
mCropLeft = 0;
@@ -169,7 +179,8 @@ void SoftVideoDecoderOMXComponent::handlePortSettingsChange(
bool strideChanged = false;
if (fakeStride) {
OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
- if (def->format.video.nStride != width || def->format.video.nSliceHeight != height) {
+ if (def->format.video.nStride != (OMX_S32)width
+ || def->format.video.nSliceHeight != (OMX_U32)height) {
strideChanged = true;
}
}
@@ -252,7 +263,7 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter(
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
if (formatParams->nPortIndex > kMaxPortIndex) {
- return OMX_ErrorUndefined;
+ return OMX_ErrorBadPortIndex;
}
if (formatParams->nIndex != 0) {
@@ -324,13 +335,25 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
if (formatParams->nPortIndex > kMaxPortIndex) {
- return OMX_ErrorUndefined;
+ return OMX_ErrorBadPortIndex;
}
if (formatParams->nIndex != 0) {
return OMX_ErrorNoMore;
}
+ if (formatParams->nPortIndex == kInputPortIndex) {
+ if (formatParams->eCompressionFormat != mCodingType
+ || formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ } else {
+ if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused
+ || formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ }
+
return OMX_ErrorNone;
}
@@ -348,7 +371,7 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
mAdaptiveMaxWidth = 0;
mAdaptiveMaxHeight = 0;
}
- updatePortDefinitions();
+ updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
return OMX_ErrorNone;
}
@@ -369,11 +392,18 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
(mIsAdaptive && outputPort) ? mAdaptiveMaxWidth : newWidth;
def->format.video.nFrameHeight =
(mIsAdaptive && outputPort) ? mAdaptiveMaxHeight : newHeight;
- def->format.video.nStride = def->format.video.nFrameWidth;
- def->format.video.nSliceHeight = def->format.video.nFrameHeight;
- def->nBufferSize =
- def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
if (outputPort) {
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+ def->nBufferSize =
+ def->format.video.nStride * def->format.video.nSliceHeight * 3 / 2;
+
+
+ OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+ // increase input buffer size if required
+ inDef->nBufferSize =
+ max(def->nBufferSize / mMinCompressionRatio, inDef->nBufferSize);
+
mWidth = newWidth;
mHeight = newHeight;
mCropLeft = 0;
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 8bff142..b2d3623 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -19,6 +19,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoftVideoEncoderOMXComponent"
#include <utils/Log.h>
+#include <utils/misc.h>
#include "include/SoftVideoEncoderOMXComponent.h"
@@ -27,6 +28,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaDefs.h>
#include <ui/GraphicBuffer.h>
@@ -34,13 +36,316 @@
namespace android {
+const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
+ OMX_COLOR_FormatYUV420Planar,
+ OMX_COLOR_FormatYUV420SemiPlanar,
+ OMX_COLOR_FormatAndroidOpaque
+};
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
SoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent(
const char *name,
+ const char *componentRole,
+ OMX_VIDEO_CODINGTYPE codingType,
+ const CodecProfileLevel *profileLevels,
+ size_t numProfileLevels,
+ int32_t width,
+ int32_t height,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
: SimpleSoftOMXComponent(name, callbacks, appData, component),
- mGrallocModule(NULL) {
+ mInputDataIsMeta(false),
+ mWidth(width),
+ mHeight(height),
+ mBitrate(192000),
+ mFramerate(30 << 16), // Q16 format
+ mColorFormat(OMX_COLOR_FormatYUV420Planar),
+ mGrallocModule(NULL),
+ mMinOutputBufferSize(384), // arbitrary, using one uncompressed macroblock
+ mMinCompressionRatio(1), // max output size is normally the input size
+ mComponentRole(componentRole),
+ mCodingType(codingType),
+ mProfileLevels(profileLevels),
+ mNumProfileLevels(numProfileLevels) {
+}
+
+void SoftVideoEncoderOMXComponent::initPorts(
+ OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
+ const char *mime, OMX_U32 minCompressionRatio) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+
+ mMinOutputBufferSize = outputBufferSize;
+ mMinCompressionRatio = minCompressionRatio;
+
+ InitOMXParams(&def);
+
+ def.nPortIndex = kInputPortIndex;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = numInputBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ // frameRate is in Q16 format.
+ def.format.video.xFramerate = mFramerate;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.nBufferAlignment = kInputBufferAlignment;
+ def.format.video.cMIMEType = const_cast<char *>("video/raw");
+ def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ def.format.video.eColorFormat = mColorFormat;
+ def.format.video.pNativeWindow = NULL;
+ // buffersize set in updatePortParams
+
+ addPort(def);
+
+ InitOMXParams(&def);
+
+ def.nPortIndex = kOutputPortIndex;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = numOutputBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = 0;
+ def.format.video.nSliceHeight = 0;
+ def.format.video.nBitrate = mBitrate;
+ def.format.video.xFramerate = 0 << 16;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.nBufferAlignment = kOutputBufferAlignment;
+ def.format.video.cMIMEType = const_cast<char *>(mime);
+ def.format.video.eCompressionFormat = mCodingType;
+ def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ def.format.video.pNativeWindow = NULL;
+ // buffersize set in updatePortParams
+
+ addPort(def);
+
+ updatePortParams();
+}
+
+void SoftVideoEncoderOMXComponent::updatePortParams() {
+ OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+ inDef->format.video.nFrameWidth = mWidth;
+ inDef->format.video.nFrameHeight = mHeight;
+ inDef->format.video.nStride = inDef->format.video.nFrameWidth;
+ inDef->format.video.nSliceHeight = inDef->format.video.nFrameHeight;
+ inDef->format.video.xFramerate = mFramerate;
+ inDef->format.video.eColorFormat = mColorFormat;
+ uint32_t rawBufferSize =
+ inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2;
+ if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+ inDef->nBufferSize = 4 + max(sizeof(buffer_handle_t), sizeof(GraphicBuffer *));
+ } else {
+ inDef->nBufferSize = rawBufferSize;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
+ outDef->format.video.nFrameWidth = mWidth;
+ outDef->format.video.nFrameHeight = mHeight;
+ outDef->format.video.nBitrate = mBitrate;
+
+ outDef->nBufferSize = max(mMinOutputBufferSize, rawBufferSize / mMinCompressionRatio);
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetPortParams(
+ const OMX_PARAM_PORTDEFINITIONTYPE *port) {
+ if (port->nPortIndex == kInputPortIndex) {
+ mWidth = port->format.video.nFrameWidth;
+ mHeight = port->format.video.nFrameHeight;
+
+ // xFramerate comes in Q16 format, in frames per second unit
+ mFramerate = port->format.video.xFramerate;
+
+ if (port->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused
+ || (port->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar
+ && port->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar
+ && port->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ mColorFormat = port->format.video.eColorFormat;
+ } else if (port->nPortIndex == kOutputPortIndex) {
+ if (port->format.video.eCompressionFormat != mCodingType
+ || port->format.video.eColorFormat != OMX_COLOR_FormatUnused) {
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ mBitrate = port->format.video.nBitrate;
+ } else {
+ return OMX_ErrorBadPortIndex;
+ }
+
+ updatePortParams();
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR param) {
+ // can include extension index OMX_INDEXEXTTYPE
+ const int32_t indexFull = index;
+
+ switch (indexFull) {
+ case OMX_IndexParamVideoErrorCorrection:
+ {
+ return OMX_ErrorNotImplemented;
+ }
+
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)param;
+
+ if (strncmp((const char *)roleParams->cRole,
+ mComponentRole,
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_ERRORTYPE err = internalSetPortParams((const OMX_PARAM_PORTDEFINITIONTYPE *)param);
+
+ if (err != OMX_ErrorNone) {
+ return err;
+ }
+
+ return SimpleSoftOMXComponent::internalSetParameter(index, param);
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ const OMX_VIDEO_PARAM_PORTFORMATTYPE* format =
+ (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
+
+ if (format->nPortIndex == kInputPortIndex) {
+ if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
+ format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+ format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+ mColorFormat = format->eColorFormat;
+
+ updatePortParams();
+ return OMX_ErrorNone;
+ } else {
+ ALOGE("Unsupported color format %i", format->eColorFormat);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ } else if (format->nPortIndex == kOutputPortIndex) {
+ if (format->eCompressionFormat == mCodingType) {
+ return OMX_ErrorNone;
+ } else {
+ return OMX_ErrorUnsupportedSetting;
+ }
+ } else {
+ return OMX_ErrorBadPortIndex;
+ }
+ }
+
+ case kStoreMetaDataExtensionIndex:
+ {
+ // storeMetaDataInBuffers
+ const StoreMetaDataInBuffersParams *storeParam =
+ (const StoreMetaDataInBuffersParams *)param;
+
+ if (storeParam->nPortIndex == kOutputPortIndex) {
+ return storeParam->bStoreMetaData ? OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
+ } else if (storeParam->nPortIndex != kInputPortIndex) {
+ return OMX_ErrorBadPortIndex;
+ }
+
+ mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
+ if (mInputDataIsMeta) {
+ mColorFormat = OMX_COLOR_FormatAndroidOpaque;
+ } else if (mColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+ mColorFormat = OMX_COLOR_FormatYUV420Planar;
+ }
+ updatePortParams();
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, param);
+ }
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR param) {
+ switch (index) {
+ case OMX_IndexParamVideoErrorCorrection:
+ {
+ return OMX_ErrorNotImplemented;
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
+
+ if (formatParams->nPortIndex == kInputPortIndex) {
+ if (formatParams->nIndex >= NELEM(kSupportedColorFormats)) {
+ return OMX_ErrorNoMore;
+ }
+
+ // Color formats, in order of preference
+ formatParams->eColorFormat = kSupportedColorFormats[formatParams->nIndex];
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ formatParams->xFramerate = mFramerate;
+ return OMX_ErrorNone;
+ } else if (formatParams->nPortIndex == kOutputPortIndex) {
+ formatParams->eCompressionFormat = mCodingType;
+ formatParams->eColorFormat = OMX_COLOR_FormatUnused;
+ formatParams->xFramerate = 0;
+ return OMX_ErrorNone;
+ } else {
+ return OMX_ErrorBadPortIndex;
+ }
+ }
+
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) param;
+
+ if (profileLevel->nPortIndex != kOutputPortIndex) {
+ ALOGE("Invalid port index: %u", profileLevel->nPortIndex);
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ if (profileLevel->nProfileIndex >= mNumProfileLevels) {
+ return OMX_ErrorNoMore;
+ }
+
+ profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile;
+ profileLevel->eLevel = mProfileLevels[profileLevel->nProfileIndex].mLevel;
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, param);
+ }
}
// static
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp
index 43e0269..5c323c1 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/tests/Utils_test.cpp
@@ -172,6 +172,13 @@ TEST_F(UtilsTest, TestMathTemplates) {
ASSERT_EQ(divUp(12, 4), 3);
ASSERT_EQ(divUp(13, 4), 4);
+ ASSERT_EQ(align(11, 4), 12);
+ ASSERT_EQ(align(12, 4), 12);
+ ASSERT_EQ(align(13, 4), 16);
+ ASSERT_EQ(align(11, 8), 16);
+ ASSERT_EQ(align(11, 2), 12);
+ ASSERT_EQ(align(11, 1), 11);
+
ASSERT_EQ(abs(5L), 5L);
ASSERT_EQ(abs(-25), 25);