Merge "Squashed commit of the following:"
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index a710546..67d940b 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -104,35 +104,62 @@
};
/*
- * The state machine of the media_recorder uses a set of different state names.
- * The mapping between the media_recorder and the pvauthorengine is shown below:
- *
- * mediarecorder pvauthorengine
- * ----------------------------------------------------------------
- * MEDIA_RECORDER_ERROR ERROR
- * MEDIA_RECORDER_IDLE IDLE
- * MEDIA_RECORDER_INITIALIZED OPENED
- * MEDIA_RECORDER_DATASOURCE_CONFIGURED
- * MEDIA_RECORDER_PREPARED INITIALIZED
- * MEDIA_RECORDER_RECORDING RECORDING
+ * The state machine of the media_recorder.
*/
enum media_recorder_states {
+ // Error state.
MEDIA_RECORDER_ERROR = 0,
+
+ // Recorder was just created.
MEDIA_RECORDER_IDLE = 1 << 0,
+
+ // Recorder has been initialized.
MEDIA_RECORDER_INITIALIZED = 1 << 1,
+
+ // Configuration of the recorder has been completed.
MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2,
+
+ // Recorder is ready to start.
MEDIA_RECORDER_PREPARED = 1 << 3,
+
+ // Recording is in progress.
MEDIA_RECORDER_RECORDING = 1 << 4,
};
// The "msg" code passed to the listener in notify.
enum media_recorder_event_type {
+ MEDIA_RECORDER_EVENT_LIST_START = 1,
MEDIA_RECORDER_EVENT_ERROR = 1,
- MEDIA_RECORDER_EVENT_INFO = 2
+ MEDIA_RECORDER_EVENT_INFO = 2,
+ MEDIA_RECORDER_EVENT_LIST_END = 99,
+
+ // Track related event types
+ MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100,
+ MEDIA_RECORDER_TRACK_EVENT_ERROR = 100,
+ MEDIA_RECORDER_TRACK_EVENT_INFO = 101,
+ MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000,
};
+/*
+ * The (part of) "what" code passed to the listener in notify.
+ * When the error or info type is track specific, the what has
+ * the following layout:
+ * the left-most 16-bit is meant for error or info type.
+ * the right-most 4-bit is meant for track id.
+ * the rest is reserved.
+ *
+ * | track id | reserved | error or info type |
+ * 31 28 16 0
+ *
+ */
enum media_recorder_error_type {
- MEDIA_RECORDER_ERROR_UNKNOWN = 1
+ MEDIA_RECORDER_ERROR_UNKNOWN = 1,
+
+ // Track related error type
+ MEDIA_RECORDER_TRACK_ERROR_LIST_START = 100,
+ MEDIA_RECORDER_TRACK_ERROR_GENERAL = 100,
+ MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME = 200,
+ MEDIA_RECORDER_TRACK_ERROR_LIST_END = 1000,
};
// The codes are distributed as follow:
@@ -141,11 +168,15 @@
//
enum media_recorder_info_type {
MEDIA_RECORDER_INFO_UNKNOWN = 1,
+
MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800,
MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801,
- MEDIA_RECORDER_INFO_COMPLETION_STATUS = 802,
- MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS = 803,
- MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS = 804,
+
+ // All track related informtional events start here
+ MEDIA_RECORDER_TRACK_INFO_LIST_START = 1000,
+ MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000,
+ MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME = 1001,
+ MEDIA_RECORDER_TRACK_INFO_LIST_END = 2000,
};
// ----------------------------------------------------------------------------
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 5c5229d..15f86ea 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -157,7 +157,7 @@
bool use32BitFileOffset() const;
bool exceedsFileDurationLimit();
bool isFileStreamable() const;
- void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
+ void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
void writeCompositionMatrix(int32_t degrees);
MPEG4Writer(const MPEG4Writer &);
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a18bedb..cee1c75 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -722,9 +722,12 @@
// Manage overrun callback
if (mActive && (cblk->framesAvailable() == 0)) {
LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
+ AutoMutex _l(cblk->lock);
if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
- mCbf(EVENT_OVERRUN, mUserData, 0);
cblk->flags |= CBLK_UNDERRUN_ON;
+ cblk->lock.unlock();
+ mCbf(EVENT_OVERRUN, mUserData, 0);
+ cblk->lock.lock();
}
}
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 8d8f67b..02e1570 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -329,6 +329,7 @@
if (mActive == 0) {
mActive = 1;
mNewPosition = cblk->server + mUpdatePeriod;
+ cblk->lock.lock();
cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
cblk->flags &= ~CBLK_DISABLED_ON;
@@ -339,7 +340,6 @@
}
LOGV("start %p before lock cblk %p", this, mCblk);
- cblk->lock.lock();
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
status = mAudioTrack->start();
@@ -893,9 +893,14 @@
// restart track if it was disabled by audioflinger due to previous underrun
if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
- cblk->flags &= ~CBLK_DISABLED_ON;
- LOGW("obtainBuffer() track %p disabled, restarting", this);
- mAudioTrack->start();
+ AutoMutex _l(cblk->lock);
+ if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
+ cblk->flags &= ~CBLK_DISABLED_ON;
+ cblk->lock.unlock();
+ LOGW("obtainBuffer() track %p disabled, restarting", this);
+ mAudioTrack->start();
+ cblk->lock.lock();
+ }
}
cblk->waitTimeMs = 0;
@@ -957,9 +962,10 @@
ssize_t written = 0;
const int8_t *src = (const int8_t *)buffer;
Buffer audioBuffer;
+ size_t frameSz = (size_t)frameSize();
do {
- audioBuffer.frameCount = userSize/frameSize();
+ audioBuffer.frameCount = userSize/frameSz;
// Calling obtainBuffer() with a negative wait count causes
// an (almost) infinite wait time.
@@ -991,7 +997,7 @@
written += toWrite;
releaseBuffer(&audioBuffer);
- } while (userSize);
+ } while (userSize >= frameSz);
return written;
}
@@ -1015,12 +1021,15 @@
// Manage underrun callback
if (mActive && (cblk->framesReady() == 0)) {
LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
+ AutoMutex _l(cblk->lock);
if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
+ cblk->flags |= CBLK_UNDERRUN_ON;
+ cblk->lock.unlock();
mCbf(EVENT_UNDERRUN, mUserData, 0);
if (cblk->server == cblk->frameCount) {
mCbf(EVENT_BUFFER_END, mUserData, 0);
}
- cblk->flags |= CBLK_UNDERRUN_ON;
+ cblk->lock.lock();
if (mSharedBuffer != 0) return false;
}
}
@@ -1279,7 +1288,12 @@
this->user = u;
// Clear flow control error condition as new data has been written/read to/from buffer.
- flags &= ~CBLK_UNDERRUN_MSK;
+ if (flags & CBLK_UNDERRUN_MSK) {
+ AutoMutex _l(lock);
+ if (flags & CBLK_UNDERRUN_MSK) {
+ flags &= ~CBLK_UNDERRUN_MSK;
+ }
+ }
return u;
}
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 0db3d1d..69846eb 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -269,7 +269,7 @@
}
if (stoppedPrematurely) {
- notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
}
close(mFd);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7a00d7a..35bc0b8 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -876,6 +876,17 @@
cropLeft, cropTop, cropRight, cropBottom);
}
+ int32_t displayWidth;
+ if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+ LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
+ mDisplayWidth = displayWidth;
+ }
+ int32_t displayHeight;
+ if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+ LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
+ mDisplayHeight = displayHeight;
+ }
+
int32_t usableWidth = cropRight - cropLeft + 1;
int32_t usableHeight = cropBottom - cropTop + 1;
if (mDisplayWidth != 0) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 5d6ea7c..edf76b5 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -52,7 +52,7 @@
class MPEG4Writer::Track {
public:
- Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+ Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
~Track();
@@ -82,6 +82,7 @@
bool mIsAvc;
bool mIsAudio;
bool mIsMPEG4;
+ int32_t mTrackId;
int64_t mTrackDurationUs;
// For realtime applications, we need to adjust the media clock
@@ -295,7 +296,12 @@
}
status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
- Track *track = new Track(this, source);
+ Mutex::Autolock l(mLock);
+ if (mStarted) {
+ LOGE("Attempt to add source AFTER recording is started");
+ return UNKNOWN_ERROR;
+ }
+ Track *track = new Track(this, source, mTracks.size());
mTracks.push_back(track);
return OK;
@@ -945,7 +951,7 @@
////////////////////////////////////////////////////////////////////////////////
MPEG4Writer::Track::Track(
- MPEG4Writer *owner, const sp<MediaSource> &source)
+ MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
: mOwner(owner),
mMeta(source->getFormat()),
mSource(source),
@@ -953,6 +959,7 @@
mPaused(false),
mResumed(false),
mStarted(false),
+ mTrackId(trackId),
mTrackDurationUs(0),
mEstimatedTrackSizeBytes(0),
mSamplesHaveSameSize(true),
@@ -2030,7 +2037,7 @@
(OK != checkCodecSpecificData())) { // no codec specific data
err = ERROR_MALFORMED;
}
- mOwner->trackProgressStatus(this, -1, err);
+ mOwner->trackProgressStatus(mTrackId, -1, err);
// Last chunk
if (mOwner->numTracks() == 1) {
@@ -2077,41 +2084,34 @@
if (mTrackEveryTimeDurationUs > 0 &&
timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
LOGV("Fire time tracking progress status at %lld us", timeUs);
- mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
+ mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
mPreviousTrackTimeUs = timeUs;
}
}
void MPEG4Writer::trackProgressStatus(
- const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
+ size_t trackId, int64_t timeUs, status_t err) {
Mutex::Autolock lock(mLock);
- int32_t nTracks = mTracks.size();
- CHECK(nTracks >= 1);
- CHECK(nTracks < 64); // Arbitrary number
-
- int32_t trackNum = 0;
- CHECK(trackNum < nTracks);
- trackNum <<= 16;
+ int32_t trackNum = (trackId << 28);
// Error notification
// Do not consider ERROR_END_OF_STREAM an error
if (err != OK && err != ERROR_END_OF_STREAM) {
- notify(MEDIA_RECORDER_EVENT_ERROR,
- trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
+ notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
+ trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
err);
return;
}
if (timeUs == -1) {
// Send completion notification
- notify(MEDIA_RECORDER_EVENT_INFO,
- trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
err);
- return;
} else {
// Send progress status
- notify(MEDIA_RECORDER_EVENT_INFO,
- trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
timeUs / 1000);
}
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3e26a95..a6a34b3 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -2215,13 +2215,15 @@
if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
onPortSettingsChanged(data1);
- } else if (data1 == kPortIndexOutput
- && data2 == OMX_IndexConfigCommonOutputCrop) {
+ } else if (data1 == kPortIndexOutput &&
+ (data2 == OMX_IndexConfigCommonOutputCrop ||
+ data2 == OMX_IndexConfigCommonScale)) {
sp<MetaData> oldOutputFormat = mOutputFormat;
initOutputFormat(mSource->getFormat());
- if (formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
+ if (data2 == OMX_IndexConfigCommonOutputCrop &&
+ formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
mOutputPortSettingsHaveChanged = true;
if (mNativeWindow != NULL) {
@@ -2240,6 +2242,39 @@
// already invalid, we'll know soon enough.
native_window_set_crop(mNativeWindow.get(), &crop);
}
+ } else if (data2 == OMX_IndexConfigCommonScale) {
+ OMX_CONFIG_SCALEFACTORTYPE scale;
+ InitOMXParams(&scale);
+ scale.nPortIndex = kPortIndexOutput;
+
+ // Change display dimension only when necessary.
+ if (OK == mOMX->getConfig(
+ mNode,
+ OMX_IndexConfigCommonScale,
+ &scale, sizeof(scale))) {
+ int32_t left, top, right, bottom;
+ CHECK(mOutputFormat->findRect(kKeyCropRect,
+ &left, &top,
+ &right, &bottom));
+
+ // The scale is in 16.16 format.
+ // scale 1.0 = 0x010000. When there is no
+ // need to change the display, skip it.
+ LOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
+ scale.xWidth, scale.xHeight);
+
+ if (scale.xWidth != 0x010000) {
+ mOutputFormat->setInt32(kKeyDisplayWidth,
+ ((right - left + 1) * scale.xWidth) >> 16);
+ mOutputPortSettingsHaveChanged = true;
+ }
+
+ if (scale.xHeight != 0x010000) {
+ mOutputFormat->setInt32(kKeyDisplayHeight,
+ ((bottom - top + 1) * scale.xHeight) >> 16);
+ mOutputPortSettingsHaveChanged = true;
+ }
+ }
}
}
break;
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 5bbba35..490129f 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -534,7 +534,8 @@
default:
{
LOGE("Should not be here, unknown nalType %d", nalType);
- CHECK(!"Should not be here");
+
+ err = ERROR_MALFORMED;
break;
}
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 2b08ab5..2702242 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1738,7 +1738,10 @@
LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun
- cblk->flags |= CBLK_DISABLED_ON;
+ {
+ AutoMutex _l(cblk->lock);
+ cblk->flags |= CBLK_DISABLED_ON;
+ }
} else if (mixerStatus != MIXER_TRACKS_READY) {
mixerStatus = MIXER_TRACKS_ENABLED;
}
@@ -1787,10 +1790,9 @@
for (size_t i = 0; i < size; i++) {
sp<Track> t = mTracks[i];
if (t->type() == streamType) {
- t->mCblk->lock.lock();
+ AutoMutex _lcblk(t->mCblk->lock);
t->mCblk->flags |= CBLK_INVALID_ON;
t->mCblk->cv.signal();
- t->mCblk->lock.unlock();
}
}
}
@@ -2948,6 +2950,7 @@
if (mCblk->framesReady() >= mCblk->frameCount ||
(mCblk->flags & CBLK_FORCEREADY_MSK)) {
+ AutoMutex _l(mCblk->lock);
mFillingUpStatus = FS_FILLED;
mCblk->flags &= ~CBLK_FORCEREADY_MSK;
return true;
@@ -3063,19 +3066,18 @@
// STOPPED state
mState = STOPPED;
- mCblk->lock.lock();
// NOTE: reset() will reset cblk->user and cblk->server with
// the risk that at the same time, the AudioMixer is trying to read
// data. In this case, getNextBuffer() would return a NULL pointer
// as audio buffer => the AudioMixer code MUST always test that pointer
// returned by getNextBuffer() is not NULL!
reset();
- mCblk->lock.unlock();
}
}
void AudioFlinger::PlaybackThread::Track::reset()
{
+ AutoMutex _l(mCblk->lock);
// Do not reset twice to avoid discarding data written just after a flush and before
// the audioflinger thread detects the track is stopped.
if (!mResetDone) {
@@ -3209,10 +3211,13 @@
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
recordThread->stop(this);
- TrackBase::reset();
- // Force overerrun condition to avoid false overrun callback until first data is
- // read from buffer
- mCblk->flags |= CBLK_UNDERRUN_ON;
+ {
+ AutoMutex _l(mCblk->lock);
+ TrackBase::reset();
+ // Force overerrun condition to avoid false overrun callback until first data is
+ // read from buffer
+ mCblk->flags |= CBLK_UNDERRUN_ON;
+ }
}
}