summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/MediaPlayerInterface.h18
-rw-r--r--include/media/stagefright/CameraSource.h2
-rw-r--r--include/media/stagefright/OMXCodec.h4
-rw-r--r--include/media/stagefright/StagefrightMediaScanner.h4
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp8
-rw-r--r--media/libstagefright/AudioPlayer.cpp4
-rw-r--r--media/libstagefright/AudioSource.cpp5
-rw-r--r--media/libstagefright/AwesomePlayer.cpp13
-rw-r--r--media/libstagefright/CameraSource.cpp2
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp5
-rw-r--r--media/libstagefright/HTTPStream.cpp96
-rw-r--r--media/libstagefright/MPEG4Writer.cpp9
-rw-r--r--media/libstagefright/OMXCodec.cpp25
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp67
-rw-r--r--media/libstagefright/codecs/aacenc/AACEncoder.cpp26
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp20
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp5
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp52
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.h8
-rw-r--r--media/libstagefright/rtsp/MyHandler.h6
-rw-r--r--media/mtp/MtpUtils.cpp6
21 files changed, 270 insertions, 115 deletions
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index c0963a6..048f041 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -126,8 +126,6 @@ public:
virtual status_t setLooping(int loop) = 0;
virtual player_type playerType() = 0;
- virtual void setNotifyCallback(void* cookie, notify_callback_f notifyFunc) {
- mCookie = cookie; mNotify = notifyFunc; }
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
//
@@ -149,9 +147,21 @@ public:
return INVALID_OPERATION;
};
- virtual void sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
+ void setNotifyCallback(
+ void* cookie, notify_callback_f notifyFunc) {
+ Mutex::Autolock autoLock(mNotifyLock);
+ mCookie = cookie; mNotify = notifyFunc;
+ }
-protected:
+ void sendEvent(int msg, int ext1=0, int ext2=0) {
+ Mutex::Autolock autoLock(mNotifyLock);
+ if (mNotify) mNotify(mCookie, msg, ext1, ext2);
+ }
+
+private:
+ friend class MediaPlayerService;
+
+ Mutex mNotifyLock;
void* mCookie;
notify_callback_f mNotify;
};
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 794355b..4a39fbf 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -158,6 +158,7 @@ protected:
int32_t mNumFramesReceived;
int64_t mLastFrameTimestampUs;
bool mStarted;
+ int32_t mNumFramesEncoded;
CameraSource(const sp<ICamera>& camera, int32_t cameraId,
Size videoSize, int32_t frameRate,
@@ -189,7 +190,6 @@ private:
List<int64_t> mFrameTimes;
int64_t mFirstFrameTimeUs;
- int32_t mNumFramesEncoded;
int32_t mNumFramesDropped;
int32_t mNumGlitches;
int64_t mGlitchDurationThresholdUs;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 3251c28..82948cb 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -47,6 +47,9 @@ struct OMXCodec : public MediaSource,
// Store meta data in video buffers
kStoreMetaDataInVideoBuffers = 32,
+
+ // Only submit one input buffer at one time.
+ kOnlySubmitOneInputBufferAtOneTime = 64,
};
static sp<MediaSource> Create(
const sp<IOMX> &omx,
@@ -192,6 +195,7 @@ private:
Condition mBufferFilled;
bool mIsMetaDataStoredInVideoBuffers;
+ bool mOnlySubmitOneBufferAtOneTime;
OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
bool isEncoder, const char *mime, const char *componentName,
diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h
index 4437eee..108acb4 100644
--- a/include/media/stagefright/StagefrightMediaScanner.h
+++ b/include/media/stagefright/StagefrightMediaScanner.h
@@ -22,8 +22,6 @@
namespace android {
-struct MediaMetadataRetriever;
-
struct StagefrightMediaScanner : public MediaScanner {
StagefrightMediaScanner();
virtual ~StagefrightMediaScanner();
@@ -35,8 +33,6 @@ struct StagefrightMediaScanner : public MediaScanner {
virtual char *extractAlbumArt(int fd);
private:
- sp<MediaMetadataRetriever> mRetriever;
-
StagefrightMediaScanner(const StagefrightMediaScanner &);
StagefrightMediaScanner &operator=(const StagefrightMediaScanner &);
};
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 65df68c..f134cba 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1239,6 +1239,14 @@ status_t StagefrightRecorder::setupVideoEncoder(
encoder_flags |= OMXCodec::kHardwareCodecsOnly;
encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
}
+
+ // Do not wait for all the input buffers to become available.
+ // This give timelapse video recording faster response in
+ // receiving output from video encoder component.
+ if (mCaptureTimeLapse) {
+ encoder_flags |= OMXCodec::kOnlySubmitOneInputBufferAtOneTime;
+ }
+
sp<MediaSource> encoder = OMXCodec::Create(
client.interface(), enc_meta,
true /* createEncoder */, cameraSource,
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 5ff934d..e7c0299 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -286,7 +286,9 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
}
if (mReachedEOS) {
- return 0;
+ memset(data, 0, size);
+
+ return size;
}
size_t size_done = 0;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 235d752..f96df18 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -91,14 +91,17 @@ status_t AudioSource::start(MetaData *params) {
mStartTimeUs = startTimeUs;
}
status_t err = mRecord->start();
-
if (err == OK) {
mGroup = new MediaBufferGroup;
mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
mStarted = true;
+ } else {
+ delete mRecord;
+ mRecord = NULL;
}
+
return err;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 11ac56c..89b3dab 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -378,14 +378,11 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
}
void AwesomePlayer::reset() {
- LOGI("reset");
-
Mutex::Autolock autoLock(mLock);
reset_l();
}
void AwesomePlayer::reset_l() {
- LOGI("reset_l");
mDisplayWidth = 0;
mDisplayHeight = 0;
@@ -411,10 +408,6 @@ void AwesomePlayer::reset_l() {
}
}
- if (mFlags & PREPARING) {
- LOGI("waiting until preparation is completes.");
- }
-
while (mFlags & PREPARING) {
mPreparedCondition.wait(mLock);
}
@@ -438,8 +431,6 @@ void AwesomePlayer::reset_l() {
}
mAudioSource.clear();
- LOGI("audio source cleared");
-
mTimeSource = NULL;
delete mAudioPlayer;
@@ -480,8 +471,6 @@ void AwesomePlayer::reset_l() {
IPCThreadState::self()->flushCommands();
}
- LOGI("video source cleared");
-
mDurationUs = -1;
mFlags = 0;
mExtractorFlags = 0;
@@ -498,8 +487,6 @@ void AwesomePlayer::reset_l() {
mFileSource.clear();
mBitrate = -1;
-
- LOGI("reset_l completed");
}
void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index b1c6b18..66e0657 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -147,8 +147,8 @@ CameraSource::CameraSource(
mNumFramesReceived(0),
mLastFrameTimestampUs(0),
mStarted(false),
- mFirstFrameTimeUs(0),
mNumFramesEncoded(0),
+ mFirstFrameTimeUs(0),
mNumFramesDropped(0),
mNumGlitches(0),
mGlitchDurationThresholdUs(200000),
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index b58b9d8..e6fe618 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -491,7 +491,10 @@ bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
}
}
- if (*timestampUs <
+ // Workaround to bypass the first 2 input frames for skipping.
+ // The first 2 output frames from the encoder are: decoder specific info and
+ // the compressed video frame data for the first input video frame.
+ if (mNumFramesEncoded >= 1 && *timestampUs <
(mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
// Skip all frames from last encoded frame until
// sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index 057868c..77a61a5 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -124,6 +124,80 @@ static status_t MyConnect(
return result;
}
+// Apparently under out linux closing a socket descriptor from one thread
+// will not unblock a pending send/recv on that socket on another thread.
+static ssize_t MySendReceive(
+ int s, void *data, size_t size, int flags, bool sendData) {
+ ssize_t result = 0;
+
+ while (size > 0) {
+ fd_set rs, ws, es;
+ FD_ZERO(&rs);
+ FD_ZERO(&ws);
+ FD_ZERO(&es);
+ FD_SET(s, sendData ? &ws : &rs);
+ FD_SET(s, &es);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000ll;
+
+ int nfds = ::select(
+ s + 1,
+ sendData ? NULL : &rs,
+ sendData ? &ws : NULL,
+ &es,
+ &tv);
+
+ if (nfds < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ result = -errno;
+ break;
+ } else if (nfds == 0) {
+ // timeout
+
+ continue;
+ }
+
+ CHECK_EQ(nfds, 1);
+
+ ssize_t nbytes =
+ sendData ? send(s, data, size, flags) : recv(s, data, size, flags);
+
+ if (nbytes < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ result = -errno;
+ break;
+ } else if (nbytes == 0) {
+ result = 0;
+ break;
+ }
+
+ data = (uint8_t *)data + nbytes;
+ size -= nbytes;
+
+ result = nbytes;
+ break;
+ }
+
+ return result;
+}
+
+static ssize_t MySend(int s, const void *data, size_t size, int flags) {
+ return MySendReceive(
+ s, const_cast<void *>(data), size, flags, true /* sendData */);
+}
+
+static ssize_t MyReceive(int s, void *data, size_t size, int flags) {
+ return MySendReceive(s, data, size, flags, false /* sendData */);
+}
+
status_t HTTPStream::connect(const char *server, int port) {
Mutex::Autolock autoLock(mLock);
@@ -202,16 +276,12 @@ status_t HTTPStream::send(const char *data, size_t size) {
}
while (size > 0) {
- ssize_t n = ::send(mSocket, data, size, 0);
+ ssize_t n = MySend(mSocket, data, size, 0);
if (n < 0) {
- if (errno == EINTR) {
- continue;
- }
-
disconnect();
- return ERROR_IO;
+ return n;
} else if (n == 0) {
disconnect();
@@ -247,12 +317,8 @@ status_t HTTPStream::receive_line(char *line, size_t size) {
for (;;) {
char c;
- ssize_t n = recv(mSocket, &c, 1, 0);
+ ssize_t n = MyReceive(mSocket, &c, 1, 0);
if (n < 0) {
- if (errno == EINTR) {
- continue;
- }
-
disconnect();
return ERROR_IO;
@@ -371,14 +437,10 @@ status_t HTTPStream::receive_header(int *http_status) {
ssize_t HTTPStream::receive(void *data, size_t size) {
size_t total = 0;
while (total < size) {
- ssize_t n = recv(mSocket, (char *)data + total, size - total, 0);
+ ssize_t n = MyReceive(mSocket, (char *)data + total, size - total, 0);
if (n < 0) {
- if (errno == EINTR) {
- continue;
- }
-
- LOGE("recv failed, errno = %d (%s)", errno, strerror(errno));
+ LOGE("recv failed, errno = %d (%s)", (int)n, strerror(-n));
disconnect();
return (ssize_t)ERROR_IO;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a47ee3a..d1a497f 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -78,6 +78,7 @@ private:
volatile bool mDone;
volatile bool mPaused;
volatile bool mResumed;
+ volatile bool mStarted;
bool mIsAvc;
bool mIsAudio;
bool mIsMPEG4;
@@ -951,6 +952,7 @@ MPEG4Writer::Track::Track(
mDone(false),
mPaused(false),
mResumed(false),
+ mStarted(false),
mTrackDurationUs(0),
mEstimatedTrackSizeBytes(0),
mSamplesHaveSameSize(true),
@@ -1279,6 +1281,7 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
mDone = false;
+ mStarted = true;
mTrackDurationUs = 0;
mReachedEOS = false;
mEstimatedTrackSizeBytes = 0;
@@ -1307,10 +1310,14 @@ status_t MPEG4Writer::Track::pause() {
status_t MPEG4Writer::Track::stop() {
LOGD("Stopping %s track", mIsAudio? "Audio": "Video");
+ if (!mStarted) {
+ LOGE("Stop() called but track is not started");
+ return ERROR_END_OF_STREAM;
+ }
+
if (mDone) {
return OK;
}
-
mDone = true;
void *dummy;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 94694a3..2a19b25 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -522,6 +522,12 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) {
if (flags & kStoreMetaDataInVideoBuffers) {
mIsMetaDataStoredInVideoBuffers = true;
}
+
+ mOnlySubmitOneBufferAtOneTime = false;
+ if (flags & kOnlySubmitOneInputBufferAtOneTime) {
+ mOnlySubmitOneBufferAtOneTime = true;
+ }
+
if (!(flags & kIgnoreCodecSpecificData)) {
uint32_t type;
const void *data;
@@ -2203,8 +2209,9 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
crop.right = right;
crop.bottom = bottom;
- CHECK_EQ(0, native_window_set_crop(
- mNativeWindow.get(), &crop));
+ // We'll ignore any errors here, if the surface is
+ // already invalid, we'll know soon enough.
+ native_window_set_crop(mNativeWindow.get(), &crop);
}
}
}
@@ -2609,7 +2616,17 @@ void OMXCodec::drainInputBuffers() {
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
for (size_t i = 0; i < buffers->size(); ++i) {
- if (!drainInputBuffer(&buffers->editItemAt(i))) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mStatus != OWNED_BY_US) {
+ continue;
+ }
+
+ if (!drainInputBuffer(info)) {
+ break;
+ }
+
+ if (mOnlySubmitOneBufferAtOneTime) {
break;
}
}
@@ -3316,7 +3333,7 @@ status_t OMXCodec::stop() {
mSource->stop();
- CODEC_LOGV("stopped");
+ CODEC_LOGI("stopped in state %d", mState);
return OK;
}
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 39b0021..be3df7c 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -28,9 +28,7 @@
namespace android {
-StagefrightMediaScanner::StagefrightMediaScanner()
- : mRetriever(new MediaMetadataRetriever) {
-}
+StagefrightMediaScanner::StagefrightMediaScanner() {}
StagefrightMediaScanner::~StagefrightMediaScanner() {}
@@ -131,37 +129,41 @@ status_t StagefrightMediaScanner::processFile(
if (status != OK) {
return status;
}
- } else if (mRetriever->setDataSource(path) == OK) {
- const char *value;
- if ((value = mRetriever->extractMetadata(
- METADATA_KEY_MIMETYPE)) != NULL) {
- client.setMimeType(value);
- }
+ } else {
+ sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
- struct KeyMap {
- const char *tag;
- int key;
- };
- static const KeyMap kKeyMap[] = {
- { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
- { "discnumber", METADATA_KEY_DISC_NUMBER },
- { "album", METADATA_KEY_ALBUM },
- { "artist", METADATA_KEY_ARTIST },
- { "albumartist", METADATA_KEY_ALBUMARTIST },
- { "composer", METADATA_KEY_COMPOSER },
- { "genre", METADATA_KEY_GENRE },
- { "title", METADATA_KEY_TITLE },
- { "year", METADATA_KEY_YEAR },
- { "duration", METADATA_KEY_DURATION },
- { "writer", METADATA_KEY_WRITER },
- { "compilation", METADATA_KEY_COMPILATION },
- };
- static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
-
- for (size_t i = 0; i < kNumEntries; ++i) {
+ if (mRetriever->setDataSource(path) == OK) {
const char *value;
- if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
- client.addStringTag(kKeyMap[i].tag, value);
+ if ((value = mRetriever->extractMetadata(
+ METADATA_KEY_MIMETYPE)) != NULL) {
+ client.setMimeType(value);
+ }
+
+ struct KeyMap {
+ const char *tag;
+ int key;
+ };
+ static const KeyMap kKeyMap[] = {
+ { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
+ { "discnumber", METADATA_KEY_DISC_NUMBER },
+ { "album", METADATA_KEY_ALBUM },
+ { "artist", METADATA_KEY_ARTIST },
+ { "albumartist", METADATA_KEY_ALBUMARTIST },
+ { "composer", METADATA_KEY_COMPOSER },
+ { "genre", METADATA_KEY_GENRE },
+ { "title", METADATA_KEY_TITLE },
+ { "year", METADATA_KEY_YEAR },
+ { "duration", METADATA_KEY_DURATION },
+ { "writer", METADATA_KEY_WRITER },
+ { "compilation", METADATA_KEY_COMPILATION },
+ };
+ static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
+
+ for (size_t i = 0; i < kNumEntries; ++i) {
+ const char *value;
+ if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
+ client.addStringTag(kKeyMap[i].tag, value);
+ }
}
}
}
@@ -180,6 +182,7 @@ char *StagefrightMediaScanner::extractAlbumArt(int fd) {
}
lseek64(fd, 0, SEEK_SET);
+ sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
if (mRetriever->setDataSource(fd, 0, size) == OK) {
sp<IMemory> mem = mRetriever->extractAlbumArt();
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index 9524884..a8b1292 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -151,7 +151,11 @@ status_t AACEncoder::start(MetaData *params) {
mInputFrame = new int16_t[mChannels * kNumSamplesPerFrame];
CHECK(mInputFrame != NULL);
- mSource->start(params);
+ status_t err = mSource->start(params);
+ if (err != OK) {
+ LOGE("AudioSource is not available");
+ return err;
+ }
mStarted = true;
@@ -159,11 +163,6 @@ status_t AACEncoder::start(MetaData *params) {
}
status_t AACEncoder::stop() {
- if (!mStarted) {
- LOGW("Call stop() when encoder has not started");
- return OK;
- }
-
if (mInputBuffer) {
mInputBuffer->release();
mInputBuffer = NULL;
@@ -172,8 +171,17 @@ status_t AACEncoder::stop() {
delete mBufferGroup;
mBufferGroup = NULL;
- mSource->stop();
+ if (mInputFrame) {
+ delete[] mInputFrame;
+ mInputFrame = NULL;
+ }
+
+ if (!mStarted) {
+ LOGW("Call stop() when encoder has not started");
+ return ERROR_END_OF_STREAM;
+ }
+ mSource->stop();
if (mEncoderHandle) {
CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
mEncoderHandle = NULL;
@@ -182,10 +190,6 @@ status_t AACEncoder::stop() {
mApiHandle = NULL;
mStarted = false;
- if (mInputFrame) {
- delete[] mInputFrame;
- mInputFrame = NULL;
- }
return OK;
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 9b6d441..c7c1409 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_TAG "OMXNodeInstance"
#include <utils/Log.h>
@@ -124,6 +124,8 @@ static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
}
status_t OMXNodeInstance::freeNode(OMXMaster *master) {
+ static int32_t kMaxNumIterations = 10;
+
// Transition the node from its current state all the way down
// to "Loaded".
// This ensures that all active buffers are properly freed even
@@ -143,9 +145,16 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) {
LOGV("forcing Executing->Idle");
sendCommand(OMX_CommandStateSet, OMX_StateIdle);
OMX_ERRORTYPE err;
+ int32_t iteration = 0;
while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
&& state != OMX_StateIdle
&& state != OMX_StateInvalid) {
+ if (++iteration > kMaxNumIterations) {
+ LOGE("component failed to enter Idle state, aborting.");
+ state = OMX_StateInvalid;
+ break;
+ }
+
usleep(100000);
}
CHECK_EQ(err, OMX_ErrorNone);
@@ -165,9 +174,16 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) {
freeActiveBuffers();
OMX_ERRORTYPE err;
+ int32_t iteration = 0;
while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
&& state != OMX_StateLoaded
&& state != OMX_StateInvalid) {
+ if (++iteration > kMaxNumIterations) {
+ LOGE("component failed to enter Loaded state, aborting.");
+ state = OMX_StateInvalid;
+ break;
+ }
+
LOGV("waiting for Loaded state...");
usleep(100000);
}
@@ -185,8 +201,10 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) {
break;
}
+ LOGV("calling destroyComponentInstance");
OMX_ERRORTYPE err = master->destroyComponentInstance(
static_cast<OMX_COMPONENTTYPE *>(mHandle));
+ LOGV("destroyComponentInstance returned err %d", err);
mHandle = NULL;
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index bbde516..8bfe285 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -359,7 +359,10 @@ sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) {
}
}
- CHECK_EQ(offset, buffer->size());
+ if (offset < buffer->size()) {
+ LOGI("ignoring %d bytes of trailing data", buffer->size() - offset);
+ }
+ CHECK_LE(offset, buffer->size());
return out;
}
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 77917b3..3e710dc 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -254,26 +254,12 @@ bool ASessionDescription::getDurationUs(int64_t *durationUs) const {
return false;
}
- if (value == "npt=now-" || value == "npt=0-") {
- return false;
- }
-
if (strncmp(value.c_str(), "npt=", 4)) {
return false;
}
- const char *s = value.c_str() + 4;
- char *end;
- double from = strtod(s, &end);
-
- if (end == s || *end != '-') {
- return false;
- }
-
- s = end + 1;
- double to = strtod(s, &end);
-
- if (end == s || *end != '\0' || to < from) {
+ float from, to;
+ if (!parseNTPRange(value.c_str() + 4, &from, &to)) {
return false;
}
@@ -307,5 +293,39 @@ void ASessionDescription::ParseFormatDesc(
}
}
+// static
+bool ASessionDescription::parseNTPRange(
+ const char *s, float *npt1, float *npt2) {
+ if (s[0] == '-') {
+ return false; // no start time available.
+ }
+
+ if (!strncmp("now", s, 3)) {
+ return false; // no absolute start time available
+ }
+
+ char *end;
+ *npt1 = strtof(s, &end);
+
+ if (end == s || *end != '-') {
+ // Failed to parse float or trailing "dash".
+ return false;
+ }
+
+ s = end + 1; // skip the dash.
+
+ if (!strncmp("now", s, 3)) {
+ return false; // no absolute end time available
+ }
+
+ *npt2 = strtof(s, &end);
+
+ if (end == s || *end != '\0') {
+ return false;
+ }
+
+ return *npt2 > *npt1;
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
index a3fa79e..b462983 100644
--- a/media/libstagefright/rtsp/ASessionDescription.h
+++ b/media/libstagefright/rtsp/ASessionDescription.h
@@ -55,6 +55,14 @@ struct ASessionDescription : public RefBase {
bool findAttribute(size_t index, const char *key, AString *value) const;
+ // parses strings of the form
+ // npt := npt-time "-" npt-time? | "-" npt-time
+ // npt-time := "now" | [0-9]+("." [0-9]*)?
+ //
+ // Returns true iff both "npt1" and "npt2" times were available,
+ // i.e. we have a fixed duration, otherwise this is live streaming.
+ static bool parseNTPRange(const char *s, float *npt1, float *npt2);
+
protected:
virtual ~ASessionDescription();
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 9bb8c46..306a9c1 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -938,13 +938,11 @@ struct MyHandler : public AHandler {
AString val;
CHECK(GetAttribute(range.c_str(), "npt", &val));
- float npt1, npt2;
- if (val == "now-" || val == "0-") {
+ float npt1, npt2;
+ if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
// This is a live stream and therefore not seekable.
return;
- } else {
- CHECK_EQ(sscanf(val.c_str(), "%f-%f", &npt1, &npt2), 2);
}
i = response->mHeaders.indexOfKey("rtp-info");
diff --git a/media/mtp/MtpUtils.cpp b/media/mtp/MtpUtils.cpp
index ab01ef5..6ec8876 100644
--- a/media/mtp/MtpUtils.cpp
+++ b/media/mtp/MtpUtils.cpp
@@ -55,7 +55,7 @@ bool parseDateTime(const char* dateTime, time_t& outSeconds) {
tm.tm_min = minute;
tm.tm_hour = hour;
tm.tm_mday = day;
- tm.tm_mon = month;
+ tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range
tm.tm_year = year - 1900;
tm.tm_wday = 0;
tm.tm_isdst = -1;
@@ -72,7 +72,9 @@ void formatDateTime(time_t seconds, char* buffer, int bufferLength) {
localtime_r(&seconds, &tm);
snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d",
- tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+ tm.tm_year + 1900,
+ tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
+ tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
} // namespace android