summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/source
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2013-05-03 21:54:17 -0700
committerChong Zhang <chz@google.com>2013-05-17 16:18:28 -0700
commit308bcaa44e578279e61be32b572fdb0b11b1e4c7 (patch)
tree3b76d5e38e37ca9f59c689bfb6aef11a75a35249 /media/libstagefright/wifi-display/source
parent6d101328e34557fa251b7d52d4d8dbf59620d099 (diff)
downloadframeworks_av-308bcaa44e578279e61be32b572fdb0b11b1e4c7.zip
frameworks_av-308bcaa44e578279e61be32b572fdb0b11b1e4c7.tar.gz
frameworks_av-308bcaa44e578279e61be32b572fdb0b11b1e4c7.tar.bz2
wifi-display: add support for metadata mode on encoder output
pass buffer_handle_t from encoder output to HDCP encryptor input Bug: 8968123 Change-Id: Iea8007ce568641e213fd2e3cf6947a6f7a95746c
Diffstat (limited to 'media/libstagefright/wifi-display/source')
-rw-r--r--media/libstagefright/wifi-display/source/Converter.cpp51
-rw-r--r--media/libstagefright/wifi-display/source/Converter.h1
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp44
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.h15
-rw-r--r--media/libstagefright/wifi-display/source/TSPacketizer.cpp24
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp19
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.h2
7 files changed, 130 insertions, 26 deletions
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 5344623..e62505d 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -438,6 +438,17 @@ void Converter::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatReleaseOutputBuffer:
+ {
+ if (mEncoder != NULL) {
+ size_t bufferIndex;
+ CHECK(msg->findInt32("bufferIndex", (int32_t*)&bufferIndex));
+ CHECK(bufferIndex < mEncoderOutputBuffers.size());
+ mEncoder->releaseOutputBuffer(bufferIndex);
+ }
+ break;
+ }
+
default:
TRESPASS();
}
@@ -645,6 +656,7 @@ status_t Converter::doMoreWork() {
size_t size;
int64_t timeUs;
uint32_t flags;
+ native_handle_t* handle = NULL;
err = mEncoder->dequeueOutputBuffer(
&bufferIndex, &offset, &size, &timeUs, &flags);
@@ -667,18 +679,43 @@ status_t Converter::doMoreWork() {
notify->setInt32("what", kWhatEOS);
notify->post();
} else {
- sp<ABuffer> buffer = new ABuffer(size);
+ sp<ABuffer> buffer;
+ sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
+
+ if (outbuf->meta()->findPointer("handle", (void**)&handle) &&
+ handle != NULL) {
+ int32_t rangeLength, rangeOffset;
+ CHECK(outbuf->meta()->findInt32("rangeOffset", &rangeOffset));
+ CHECK(outbuf->meta()->findInt32("rangeLength", &rangeLength));
+ outbuf->meta()->setPointer("handle", NULL);
+
+ // MediaSender will post the following message when HDCP
+ // is done, to release the output buffer back to encoder.
+ sp<AMessage> notify(new AMessage(
+ kWhatReleaseOutputBuffer, id()));
+ notify->setInt32("bufferIndex", bufferIndex);
+
+ buffer = new ABuffer(
+ rangeLength > (int32_t)size ? rangeLength : size);
+ buffer->meta()->setPointer("handle", handle);
+ buffer->meta()->setInt32("rangeOffset", rangeOffset);
+ buffer->meta()->setInt32("rangeLength", rangeLength);
+ buffer->meta()->setMessage("notify", notify);
+ } else {
+ buffer = new ABuffer(size);
+ }
+
buffer->meta()->setInt64("timeUs", timeUs);
ALOGV("[%s] time %lld us (%.2f secs)",
mIsVideo ? "video" : "audio", timeUs, timeUs / 1E6);
- memcpy(buffer->data(),
- mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset,
- size);
+ memcpy(buffer->data(), outbuf->base() + offset, size);
if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
- mOutputFormat->setBuffer("csd-0", buffer);
+ if (!handle) {
+ mOutputFormat->setBuffer("csd-0", buffer);
+ }
} else {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatAccessUnit);
@@ -687,7 +724,9 @@ status_t Converter::doMoreWork() {
}
}
- mEncoder->releaseOutputBuffer(bufferIndex);
+ if (!handle) {
+ mEncoder->releaseOutputBuffer(bufferIndex);
+ }
if (flags & MediaCodec::BUFFER_FLAG_EOS) {
break;
diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h
index ba297c4..fceef55 100644
--- a/media/libstagefright/wifi-display/source/Converter.h
+++ b/media/libstagefright/wifi-display/source/Converter.h
@@ -66,6 +66,7 @@ struct Converter : public AHandler {
kWhatMediaPullerNotify,
kWhatEncoderActivity,
kWhatDropAFrame,
+ kWhatReleaseOutputBuffer,
};
void shutdownAsync();
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index cacfcca..7f0ba96 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -378,7 +378,9 @@ status_t WifiDisplaySource::PlaybackSession::init(
bool usePCMAudio,
bool enableVideo,
VideoFormats::ResolutionType videoResolutionType,
- size_t videoResolutionIndex) {
+ size_t videoResolutionIndex,
+ VideoFormats::ProfileType videoProfileType,
+ VideoFormats::LevelType videoLevelType) {
sp<AMessage> notify = new AMessage(kWhatMediaSenderNotify, id());
mMediaSender = new MediaSender(mNetSession, notify);
looper()->registerHandler(mMediaSender);
@@ -390,7 +392,9 @@ status_t WifiDisplaySource::PlaybackSession::init(
usePCMAudio,
enableVideo,
videoResolutionType,
- videoResolutionIndex);
+ videoResolutionIndex,
+ videoProfileType,
+ videoLevelType);
if (err == OK) {
err = mMediaSender->initAsync(
@@ -870,7 +874,9 @@ status_t WifiDisplaySource::PlaybackSession::setupPacketizer(
bool usePCMAudio,
bool enableVideo,
VideoFormats::ResolutionType videoResolutionType,
- size_t videoResolutionIndex) {
+ size_t videoResolutionIndex,
+ VideoFormats::ProfileType videoProfileType,
+ VideoFormats::LevelType videoLevelType) {
CHECK(enableAudio || enableVideo);
if (!mMediaPath.empty()) {
@@ -879,7 +885,8 @@ status_t WifiDisplaySource::PlaybackSession::setupPacketizer(
if (enableVideo) {
status_t err = addVideoSource(
- videoResolutionType, videoResolutionIndex);
+ videoResolutionType, videoResolutionIndex, videoProfileType,
+ videoLevelType);
if (err != OK) {
return err;
@@ -895,9 +902,13 @@ status_t WifiDisplaySource::PlaybackSession::setupPacketizer(
status_t WifiDisplaySource::PlaybackSession::addSource(
bool isVideo, const sp<MediaSource> &source, bool isRepeaterSource,
- bool usePCMAudio, size_t *numInputBuffers) {
+ bool usePCMAudio, unsigned profileIdc, unsigned levelIdc,
+ unsigned constraintSet, size_t *numInputBuffers) {
CHECK(!usePCMAudio || !isVideo);
CHECK(!isRepeaterSource || isVideo);
+ CHECK(!profileIdc || isVideo);
+ CHECK(!levelIdc || isVideo);
+ CHECK(!constraintSet || isVideo);
sp<ALooper> pullLooper = new ALooper;
pullLooper->setName("pull_looper");
@@ -927,9 +938,12 @@ status_t WifiDisplaySource::PlaybackSession::addSource(
if (isVideo) {
format->setInt32("store-metadata-in-buffers", true);
-
+ format->setInt32("store-metadata-in-buffers-output", (mHDCP != NULL));
format->setInt32(
"color-format", OMX_COLOR_FormatAndroidOpaque);
+ format->setInt32("profile-idc", profileIdc);
+ format->setInt32("level-idc", levelIdc);
+ format->setInt32("constraint-set", constraintSet);
}
notify = new AMessage(kWhatConverterNotify, id());
@@ -990,7 +1004,9 @@ status_t WifiDisplaySource::PlaybackSession::addSource(
status_t WifiDisplaySource::PlaybackSession::addVideoSource(
VideoFormats::ResolutionType videoResolutionType,
- size_t videoResolutionIndex) {
+ size_t videoResolutionIndex,
+ VideoFormats::ProfileType videoProfileType,
+ VideoFormats::LevelType videoLevelType) {
size_t width, height, framesPerSecond;
bool interlaced;
CHECK(VideoFormats::GetConfiguration(
@@ -1001,6 +1017,14 @@ status_t WifiDisplaySource::PlaybackSession::addVideoSource(
&framesPerSecond,
&interlaced));
+ unsigned profileIdc, levelIdc, constraintSet;
+ CHECK(VideoFormats::GetProfileLevel(
+ videoProfileType,
+ videoLevelType,
+ &profileIdc,
+ &levelIdc,
+ &constraintSet));
+
sp<SurfaceMediaSource> source = new SurfaceMediaSource(width, height);
source->setUseAbsoluteTimestamps();
@@ -1011,7 +1035,8 @@ status_t WifiDisplaySource::PlaybackSession::addVideoSource(
size_t numInputBuffers;
status_t err = addSource(
true /* isVideo */, videoSource, true /* isRepeaterSource */,
- false /* usePCMAudio */, &numInputBuffers);
+ false /* usePCMAudio */, profileIdc, levelIdc, constraintSet,
+ &numInputBuffers);
if (err != OK) {
return err;
@@ -1034,7 +1059,8 @@ status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) {
if (audioSource->initCheck() == OK) {
return addSource(
false /* isVideo */, audioSource, false /* isRepeaterSource */,
- usePCMAudio, NULL /* numInputBuffers */);
+ usePCMAudio, 0 /* profileIdc */, 0 /* levelIdc */,
+ 0 /* constraintSet */, NULL /* numInputBuffers */);
}
ALOGW("Unable to instantiate audio source");
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index 39086a1..5c8ee94 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -53,7 +53,9 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
bool usePCMAudio,
bool enableVideo,
VideoFormats::ResolutionType videoResolutionType,
- size_t videoResolutionIndex);
+ size_t videoResolutionIndex,
+ VideoFormats::ProfileType videoProfileType,
+ VideoFormats::LevelType videoLevelType);
void destroyAsync();
@@ -130,18 +132,25 @@ private:
bool usePCMAudio,
bool enableVideo,
VideoFormats::ResolutionType videoResolutionType,
- size_t videoResolutionIndex);
+ size_t videoResolutionIndex,
+ VideoFormats::ProfileType videoProfileType,
+ VideoFormats::LevelType videoLevelType);
status_t addSource(
bool isVideo,
const sp<MediaSource> &source,
bool isRepeaterSource,
bool usePCMAudio,
+ unsigned profileIdc,
+ unsigned levelIdc,
+ unsigned contraintSet,
size_t *numInputBuffers);
status_t addVideoSource(
VideoFormats::ResolutionType videoResolutionType,
- size_t videoResolutionIndex);
+ size_t videoResolutionIndex,
+ VideoFormats::ProfileType videoProfileType,
+ VideoFormats::LevelType videoLevelType);
status_t addAudioSource(bool usePCMAudio);
diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
index 2c4a373..c674700 100644
--- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp
+++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
@@ -261,12 +261,24 @@ void TSPacketizer::Track::finalize() {
data[0] = 40; // descriptor_tag
data[1] = 4; // descriptor_length
- CHECK_GE(mCSD.size(), 1u);
- const sp<ABuffer> &sps = mCSD.itemAt(0);
- CHECK(!memcmp("\x00\x00\x00\x01", sps->data(), 4));
- CHECK_GE(sps->size(), 7u);
- // profile_idc, constraint_set*, level_idc
- memcpy(&data[2], sps->data() + 4, 3);
+ if (mCSD.size() > 0) {
+ CHECK_GE(mCSD.size(), 1u);
+ const sp<ABuffer> &sps = mCSD.itemAt(0);
+ CHECK(!memcmp("\x00\x00\x00\x01", sps->data(), 4));
+ CHECK_GE(sps->size(), 7u);
+ // profile_idc, constraint_set*, level_idc
+ memcpy(&data[2], sps->data() + 4, 3);
+ } else {
+ int32_t profileIdc, levelIdc, constraintSet;
+ CHECK(mFormat->findInt32("profile-idc", &profileIdc));
+ CHECK(mFormat->findInt32("level-idc", &levelIdc));
+ CHECK(mFormat->findInt32("constraint-set", &constraintSet));
+ CHECK_GE(profileIdc, 0u);
+ CHECK_GE(levelIdc, 0u);
+ data[2] = profileIdc; // profile_idc
+ data[3] = constraintSet; // constraint_set*
+ data[4] = levelIdc; // level_idc
+ }
// AVC_still_present=0, AVC_24_hour_picture_flag=0, reserved
data[5] = 0x3f;
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index b2cc66c..0b714f0 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -74,6 +74,11 @@ WifiDisplaySource::WifiDisplaySource(
mSupportedSourceVideoFormats.setNativeResolution(
VideoFormats::RESOLUTION_CEA, 5); // 1280x720 p30
+
+ mSupportedSourceVideoFormats.setProfileLevel(
+ VideoFormats::RESOLUTION_CEA, 5,
+ VideoFormats::PROFILE_CHP, // Constrained High Profile
+ VideoFormats::LEVEL_32); // Level 3.2
}
WifiDisplaySource::~WifiDisplaySource() {
@@ -631,6 +636,9 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) {
chosenVideoFormat.disableAll();
chosenVideoFormat.setNativeResolution(
mChosenVideoResolutionType, mChosenVideoResolutionIndex);
+ chosenVideoFormat.setProfileLevel(
+ mChosenVideoResolutionType, mChosenVideoResolutionIndex,
+ mChosenVideoProfile, mChosenVideoLevel);
body.append(chosenVideoFormat.getFormatSpec(true /* forM4Message */));
body.append("\r\n");
@@ -859,7 +867,9 @@ status_t WifiDisplaySource::onReceiveM3Response(
mSupportedSinkVideoFormats,
mSupportedSourceVideoFormats,
&mChosenVideoResolutionType,
- &mChosenVideoResolutionIndex)) {
+ &mChosenVideoResolutionIndex,
+ &mChosenVideoProfile,
+ &mChosenVideoLevel)) {
ALOGE("Sink and source share no commonly supported video "
"formats.");
@@ -878,6 +888,9 @@ status_t WifiDisplaySource::onReceiveM3Response(
ALOGI("Picked video resolution %u x %u %c%u",
width, height, interlaced ? 'i' : 'p', framesPerSecond);
+
+ ALOGI("Picked AVC profile %d, level %d",
+ mChosenVideoProfile, mChosenVideoLevel);
} else {
ALOGI("Sink doesn't support video at all.");
}
@@ -1271,7 +1284,9 @@ status_t WifiDisplaySource::onSetupRequest(
mUsingPCMAudio,
mSinkSupportsVideo,
mChosenVideoResolutionType,
- mChosenVideoResolutionIndex);
+ mChosenVideoResolutionIndex,
+ mChosenVideoProfile,
+ mChosenVideoLevel);
if (err != OK) {
looper()->unregisterHandler(playbackSession->id());
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 3efa0b4..64186fc 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -134,6 +134,8 @@ private:
VideoFormats::ResolutionType mChosenVideoResolutionType;
size_t mChosenVideoResolutionIndex;
+ VideoFormats::ProfileType mChosenVideoProfile;
+ VideoFormats::LevelType mChosenVideoLevel;
bool mSinkSupportsAudio;