Merge "Camera hal change for 0-memcpy in media recording framework"
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 2bb7783..1d94160 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -33,7 +33,11 @@
public MediaBufferObserver {
enum CreationFlags {
kPreferSoftwareCodecs = 1,
- kIgnoreCodecSpecificData = 2
+ kIgnoreCodecSpecificData = 2,
+
+ // The client wants to access the output buffer's video
+ // data for example for thumbnail extraction.
+ kClientNeedsFramebuffer = 4,
};
static sp<MediaSource> Create(
const sp<IOMX> &omx,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index a0b7f70..ad6cb5b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1079,6 +1079,32 @@
return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
}
+void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
+ if (!mSeeking) {
+ return;
+ }
+
+ if (mAudioPlayer != NULL) {
+ LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
+
+ // If we don't have a video time, seek audio to the originally
+ // requested seek time instead.
+
+ mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
+ mAudioPlayer->resume();
+ mWatchForAudioSeekComplete = true;
+ mWatchForAudioEOS = true;
+ } else if (!mSeekNotificationSent) {
+ // If we're playing video only, report seek complete now,
+ // otherwise audio player will notify us later.
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ }
+
+ mFlags |= FIRST_FRAME;
+ mSeeking = false;
+ mSeekNotificationSent = false;
+}
+
void AwesomePlayer::onVideoEvent() {
Mutex::Autolock autoLock(mLock);
if (!mVideoEventPending) {
@@ -1142,6 +1168,14 @@
continue;
}
+ // So video playback is complete, but we may still have
+ // a seek request pending that needs to be applied
+ // to the audio track.
+ if (mSeeking) {
+ LOGV("video stream ended while seeking!");
+ }
+ finishSeekIfNecessary(-1);
+
mFlags |= VIDEO_AT_EOS;
postStreamDoneEvent_l(err);
return;
@@ -1168,24 +1202,7 @@
mVideoTimeUs = timeUs;
}
- if (mSeeking) {
- if (mAudioPlayer != NULL) {
- LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
-
- mAudioPlayer->seekTo(timeUs);
- mAudioPlayer->resume();
- mWatchForAudioSeekComplete = true;
- mWatchForAudioEOS = true;
- } else if (!mSeekNotificationSent) {
- // If we're playing video only, report seek complete now,
- // otherwise audio player will notify us later.
- notifyListener_l(MEDIA_SEEK_COMPLETE);
- }
-
- mFlags |= FIRST_FRAME;
- mSeeking = false;
- mSeekNotificationSent = false;
- }
+ finishSeekIfNecessary(timeUs);
TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index b3daf67..81a2b0d 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -725,6 +725,14 @@
size_t PES_packet_length = accessUnit->size() + 8;
+ if (PES_packet_length >= 65536) {
+ // This really should only happen for video.
+ CHECK_EQ(stream_id, 0xe0u);
+
+ // It's valid to set this to 0 for video according to the specs.
+ PES_packet_length = 0;
+ }
+
uint8_t *ptr = buffer->data();
*ptr++ = 0x47;
*ptr++ = 0x40 | (PID >> 8);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 5e70888..4be1b38 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -510,12 +510,29 @@
LOGV("Attempting to allocate OMX node '%s'", componentName);
+ uint32_t quirks = getComponentQuirks(componentName, createEncoder);
+
+ if (!createEncoder
+ && (quirks & kOutputBuffersAreUnreadable)
+ && (flags & kClientNeedsFramebuffer)) {
+ if (strncmp(componentName, "OMX.SEC.", 8)) {
+ // For OMX.SEC.* decoders we can enable a special mode that
+ // gives the client access to the framebuffer contents.
+
+ LOGW("Component '%s' does not give the client access to "
+ "the framebuffer contents. Skipping.",
+ componentName);
+
+ continue;
+ }
+ }
+
status_t err = omx->allocateNode(componentName, observer, &node);
if (err == OK) {
LOGV("Successfully allocated OMX node '%s'", componentName);
sp<OMXCodec> codec = new OMXCodec(
- omx, node, getComponentQuirks(componentName, createEncoder),
+ omx, node, quirks,
createEncoder, mime, componentName,
source);
@@ -698,6 +715,33 @@
initOutputFormat(meta);
+ if ((flags & kClientNeedsFramebuffer)
+ && !strncmp(mComponentName, "OMX.SEC.", 8)) {
+ OMX_INDEXTYPE index;
+
+ status_t err =
+ mOMX->getExtensionIndex(
+ mNode,
+ "OMX.SEC.index.ThumbnailMode",
+ &index);
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_BOOL enable = OMX_TRUE;
+ err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
+
+ if (err != OK) {
+ CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
+ "returned error 0x%08x", err);
+
+ return err;
+ }
+
+ mQuirks &= ~kOutputBuffersAreUnreadable;
+ }
+
return OK;
}
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index af9c70c..a800a93 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -112,7 +112,7 @@
sp<MediaSource> decoder =
OMXCodec::Create(
client->interface(), source->getFormat(), false, source,
- NULL, flags);
+ NULL, flags | OMXCodec::kClientNeedsFramebuffer);
if (decoder.get() == NULL) {
LOGV("unable to instantiate video decoder.");
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 7683113..8aa1b15 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -54,7 +54,10 @@
Mutex::Autolock autoLock(mLock);
ssize_t index = mHandlers.indexOfKey(handlerID);
- CHECK_GE(index, 0);
+
+ if (index < 0) {
+ return;
+ }
const HandlerInfo &info = mHandlers.valueAt(index);
@@ -84,7 +87,8 @@
if (looper == NULL) {
LOGW("failed to post message. "
- "Target handler still registered, but object gone.");
+ "Target handler %d still registered, but object gone.",
+ msg->target());
mHandlers.removeItemsAt(index);
return;
@@ -111,7 +115,8 @@
if (handler == NULL) {
LOGW("failed to deliver message. "
- "Target handler registered, but object gone.");
+ "Target handler %d registered, but object gone.",
+ msg->target());
mHandlers.removeItemsAt(index);
return;
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 5a1d7e7..0837be8 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -261,6 +261,8 @@
bool getBitrate(int64_t *bitrate);
+ void finishSeekIfNecessary(int64_t videoTimeUs);
+
AwesomePlayer(const AwesomePlayer &);
AwesomePlayer &operator=(const AwesomePlayer &);
};