Loading media/libstagefright/MPEG4Writer.cpp +110 −55 Original line number Original line Diff line number Diff line Loading @@ -945,10 +945,30 @@ status_t MPEG4Writer::start(MetaData *param) { mInMemoryCache = NULL; mInMemoryCache = NULL; mInMemoryCacheOffset = 0; mInMemoryCacheOffset = 0; status_t err = OK; int32_t is4bitTrackId = false; if (param && param->findInt32(kKey4BitTrackIds, &is4bitTrackId) && is4bitTrackId) { err = validateAllTracksId(true); } else { err = validateAllTracksId(false); } if (err != OK) { return err; } ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d", ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d", mHasMoovBox, mHasFileLevelMeta); mHasMoovBox, mHasFileLevelMeta); err = startWriterThread(); if (err != OK) { return err; } err = setupAndStartLooper(); if (err != OK) { return err; } writeFtypBox(param); writeFtypBox(param); mFreeBoxOffset = mOffset; mFreeBoxOffset = mOffset; Loading Loading @@ -980,22 +1000,22 @@ status_t MPEG4Writer::start(MetaData *param) { seekOrPostError(mFd, mMdatOffset, SEEK_SET); seekOrPostError(mFd, mMdatOffset, SEEK_SET); write("\x00\x00\x00\x01mdat????????", 16); write("\x00\x00\x00\x01mdat????????", 16); status_t err = startWriterThread(); /* Confirm whether the writing of the initial file atoms, ftyp and free, if (err != OK) { * are written to the file properly by posting kWhatNoIOErrorSoFar to the return err; * MP4WtrCtrlHlpLooper that's handling write and seek errors also. If there } * was kWhatIOError, the following two scenarios should be handled. * 1) If kWhatIOError was delivered and processed, MP4WtrCtrlHlpLooper setupAndStartLooper(); * would have stopped all threads gracefully already and posting * kWhatNoIOErrorSoFar would fail. int32_t is4bitTrackId = false; * 2) If kWhatIOError wasn't delivered or getting processed, if (param && param->findInt32(kKey4BitTrackIds, &is4bitTrackId) && is4bitTrackId) { * kWhatNoIOErrorSoFar should get posted successfully. Wait for err = validateAllTracksId(true); * response from MP4WtrCtrlHlpLooper. } */ else { sp<AMessage> msg = new AMessage(kWhatNoIOErrorSoFar, mReflector); err = validateAllTracksId(false); sp<AMessage> response; } err = msg->postAndAwaitResponse(&response); if (err != OK) { if (err != OK || !response->findInt32("err", &err) || err != OK) { return err; return ERROR_IO; } } err = startTracks(param); err = startTracks(param); Loading Loading @@ -1025,13 +1045,16 @@ status_t MPEG4Writer::stopWriterThread() { } } void *dummy; void *dummy; status_t err = pthread_join(mThread, &dummy); status_t err = OK; WARN_UNLESS(err == 0, "stopWriterThread pthread_join err: %d", err); int retVal = pthread_join(mThread, &dummy); if (retVal == 0) { err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGD("WriterThread stopped. Status:%d", err); } else { ALOGE("stopWriterThread pthread_join status:%d", retVal); err = UNKNOWN_ERROR; } mWriterThreadStarted = false; mWriterThreadStarted = false; WARN_UNLESS(err == 0, "stopWriterThread pthread_join retVal: %d", err); ALOGD("Writer thread stopped"); return err; return err; } } Loading Loading @@ -1089,23 +1112,26 @@ void MPEG4Writer::writeCompositionMatrix(int degrees) { status_t MPEG4Writer::release() { status_t MPEG4Writer::release() { ALOGD("release()"); ALOGD("release()"); if (mPreAllocationEnabled) { status_t err = OK; truncatePreAllocation(); if (!truncatePreAllocation()) { } if (err == OK) { err = ERROR_IO; } int err = OK; } int retVal = fsync(mFd); if (fsync(mFd) != 0) { WARN_UNLESS(retVal == 0, "fsync err:%s(%d)", std::strerror(errno), errno); ALOGW("(ignored)fsync err:%s(%d)", std::strerror(errno), errno); err |= retVal; // Don't bubble up fsync error, b/157291505. retVal = close(mFd); // if (err == OK) { err = ERROR_IO; } WARN_UNLESS(retVal == 0, "close err:%s(%d)", std::strerror(errno), errno); } err |= retVal; if (close(mFd) != 0) { ALOGE("close err:%s(%d)", std::strerror(errno), errno); if (err == OK) { err = ERROR_IO; } } mFd = -1; mFd = -1; if (mNextFd != -1) { if (mNextFd != -1) { retVal = close(mNextFd); if (close(mNextFd) != 0) { ALOGE("close(mNextFd) error:%s(%d)", std::strerror(errno), errno); } if (err == OK) { err = ERROR_IO; } mNextFd = -1; mNextFd = -1; WARN_UNLESS(retVal == 0, "close mNextFd error:%s(%d)", std::strerror(errno), errno); err |= retVal; } } stopAndReleaseLooper(); stopAndReleaseLooper(); mInitCheck = NO_INIT; mInitCheck = NO_INIT; Loading Loading @@ -1165,7 +1191,7 @@ status_t MPEG4Writer::reset(bool stopSource) { for (List<Track *>::iterator it = mTracks.begin(); for (List<Track *>::iterator it = mTracks.begin(); it != mTracks.end(); ++it) { it != mTracks.end(); ++it) { status_t trackErr = (*it)->stop(stopSource); status_t trackErr = (*it)->stop(stopSource); WARN_UNLESS(trackErr == 0, "%s track stopped with an error", WARN_UNLESS(trackErr == OK, "%s track stopped with an error", (*it)->getTrackType()); (*it)->getTrackType()); if (err == OK && trackErr != OK) { if (err == OK && trackErr != OK) { err = trackErr; err = trackErr; Loading Loading @@ -1254,7 +1280,11 @@ status_t MPEG4Writer::reset(bool stopSource) { CHECK(mBoxes.empty()); CHECK(mBoxes.empty()); err = release(); status_t errRelease = release(); // Prioritize the error that occurred before release(). if (err == OK) { err = errRelease; } return err; return err; } } Loading Loading @@ -1577,9 +1607,8 @@ void MPEG4Writer::writeOrPostError(int fd, const void* buf, size_t count) { // Can't guarantee that file is usable or write would succeed anymore, hence signal to stop. // Can't guarantee that file is usable or write would succeed anymore, hence signal to stop. sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); msg->setInt32("errno", errno); msg->setInt32("err", ERROR_IO); status_t err = msg->post(); WARN_UNLESS(msg->post() == OK, "writeOrPostError:error posting ERROR_IO"); ALOGE("writeOrPostError post:%d", err); } } void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) { void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) { Loading @@ -1597,9 +1626,8 @@ void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) { // Can't guarantee that file is usable or seek would succeed anymore, hence signal to stop. // Can't guarantee that file is usable or seek would succeed anymore, hence signal to stop. sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); msg->setInt32("errno", errno); msg->setInt32("err", ERROR_IO); status_t err = msg->post(); WARN_UNLESS(msg->post() == OK, "seekOrPostError:error posting ERROR_IO"); ALOGE("seekOrPostError post:%d", err); } } void MPEG4Writer::beginBox(uint32_t id) { void MPEG4Writer::beginBox(uint32_t id) { Loading Loading @@ -1838,7 +1866,7 @@ bool MPEG4Writer::preAllocate(uint64_t wantSize) { if (res == -1) { if (res == -1) { ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd); ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd); sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector); sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector); msg->setInt32("errno", errno); msg->setInt32("err", ERROR_IO); status_t err = msg->post(); status_t err = msg->post(); mFallocateErr = true; mFallocateErr = true; ALOGD("preAllocation post:%d", err); ALOGD("preAllocation post:%d", err); Loading @@ -1850,6 +1878,9 @@ bool MPEG4Writer::preAllocate(uint64_t wantSize) { } } bool MPEG4Writer::truncatePreAllocation() { bool MPEG4Writer::truncatePreAllocation() { if (!mPreAllocationEnabled) return true; bool status = true; bool status = true; off64_t endOffset = std::max(mMdatEndOffset, mOffset); off64_t endOffset = std::max(mMdatEndOffset, mOffset); /* if mPreAllocateFileEndOffset >= endOffset, then preallocation logic works good. (diff >= 0). /* if mPreAllocateFileEndOffset >= endOffset, then preallocation logic works good. (diff >= 0). Loading @@ -1861,6 +1892,10 @@ bool MPEG4Writer::truncatePreAllocation() { if(ftruncate(mFd, endOffset) == -1) { if(ftruncate(mFd, endOffset) == -1) { ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd); ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd); status = false; status = false; /* No need to post and handle(stop & notify client) error like it's done in preAllocate(), * because ftruncate() is called during release() only and the error here would be * reported from there as this function is returning false on any error in ftruncate(). */ } } return status; return status; } } Loading Loading @@ -2153,14 +2188,17 @@ void MPEG4Writer::Track::addOneElstTableEntry( mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction)); mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction)); } } void MPEG4Writer::setupAndStartLooper() { status_t MPEG4Writer::setupAndStartLooper() { status_t err = OK; if (mLooper == nullptr) { if (mLooper == nullptr) { mLooper = new ALooper; mLooper = new ALooper; mLooper->setName("MP4WtrCtrlHlpLooper"); mLooper->setName("MP4WtrCtrlHlpLooper"); mLooper->start(); err = mLooper->start(); mReflector = new AHandlerReflector<MPEG4Writer>(this); mReflector = new AHandlerReflector<MPEG4Writer>(this); mLooper->registerHandler(mReflector); mLooper->registerHandler(mReflector); } } ALOGD("MP4WtrCtrlHlpLooper Started"); return err; } } void MPEG4Writer::stopAndReleaseLooper() { void MPEG4Writer::stopAndReleaseLooper() { Loading Loading @@ -2399,23 +2437,35 @@ void MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) { case kWhatIOError: { case kWhatIOError: { ALOGE("kWhatIOError"); ALOGE("kWhatIOError"); int32_t err; int32_t err; CHECK(msg->findInt32("errno", &err)); CHECK(msg->findInt32("err", &err)); // Stop tracks' threads and main writer thread. // Stop tracks' threads and main writer thread. stop(); stop(); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); break; break; } } // fallocate() failed, hence notify app about it and stop(). // fallocate() failed, hence stop() and notify app. case kWhatFallocateError: { case kWhatFallocateError: { ALOGE("kWhatFallocateError"); ALOGE("kWhatFallocateError"); int32_t err; int32_t err; CHECK(msg->findInt32("errno", &err)); CHECK(msg->findInt32("err", &err)); // Stop tracks' threads and main writer thread. // Stop tracks' threads and main writer thread. stop(); stop(); //TODO: introduce a suitable MEDIA_RECORDER_ERROR_* instead MEDIA_RECORDER_ERROR_UNKNOWN? //TODO: introduce a suitable MEDIA_RECORDER_ERROR_* instead MEDIA_RECORDER_ERROR_UNKNOWN? notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); break; break; } } /* Response to kWhatNoIOErrorSoFar would be OK always as of now. * Responding with other options could be added later if required. */ case kWhatNoIOErrorSoFar: { ALOGD("kWhatNoIOErrorSoFar"); sp<AMessage> response = new AMessage; response->setInt32("err", OK); sp<AReplyToken> replyID; CHECK(msg->senderAwaitsResponse(&replyID)); response->postReply(replyID); break; } default: default: TRESPASS(); TRESPASS(); } } Loading Loading @@ -2778,11 +2828,16 @@ status_t MPEG4Writer::Track::stop(bool stopSource) { mDone = true; mDone = true; void *dummy; void *dummy; status_t err = pthread_join(mThread, &dummy); status_t err = OK; WARN_UNLESS(err == 0, "track::stop: pthread_join status:%d", err); int retVal = pthread_join(mThread, &dummy); status_t threadRetVal = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); if (retVal == 0) { WARN_UNLESS(threadRetVal == 0, "%s track stopped. Status :%d. %s source", err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGD("%s track stopped. Status:%d. %s source", getTrackType(), err, stopSource ? "Stop" : "Not Stop"); getTrackType(), err, stopSource ? "Stop" : "Not Stop"); } else { ALOGE("track::stop: pthread_join retVal:%d", retVal); err = UNKNOWN_ERROR; } mStarted = false; mStarted = false; return err; return err; } } Loading media/libstagefright/include/media/stagefright/MPEG4Writer.h +3 −2 Original line number Original line Diff line number Diff line Loading @@ -87,7 +87,8 @@ private: enum { enum { kWhatSwitch = 'swch', kWhatSwitch = 'swch', kWhatIOError = 'ioer', kWhatIOError = 'ioer', kWhatFallocateError = 'faer' kWhatFallocateError = 'faer', kWhatNoIOErrorSoFar = 'noie' }; }; int mFd; int mFd; Loading Loading @@ -231,7 +232,7 @@ private: status_t stopWriterThread(); status_t stopWriterThread(); static void *ThreadWrapper(void *me); static void *ThreadWrapper(void *me); void threadFunc(); void threadFunc(); void setupAndStartLooper(); status_t setupAndStartLooper(); void stopAndReleaseLooper(); void stopAndReleaseLooper(); // Buffer a single chunk to be written out later. // Buffer a single chunk to be written out later. Loading Loading
media/libstagefright/MPEG4Writer.cpp +110 −55 Original line number Original line Diff line number Diff line Loading @@ -945,10 +945,30 @@ status_t MPEG4Writer::start(MetaData *param) { mInMemoryCache = NULL; mInMemoryCache = NULL; mInMemoryCacheOffset = 0; mInMemoryCacheOffset = 0; status_t err = OK; int32_t is4bitTrackId = false; if (param && param->findInt32(kKey4BitTrackIds, &is4bitTrackId) && is4bitTrackId) { err = validateAllTracksId(true); } else { err = validateAllTracksId(false); } if (err != OK) { return err; } ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d", ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d", mHasMoovBox, mHasFileLevelMeta); mHasMoovBox, mHasFileLevelMeta); err = startWriterThread(); if (err != OK) { return err; } err = setupAndStartLooper(); if (err != OK) { return err; } writeFtypBox(param); writeFtypBox(param); mFreeBoxOffset = mOffset; mFreeBoxOffset = mOffset; Loading Loading @@ -980,22 +1000,22 @@ status_t MPEG4Writer::start(MetaData *param) { seekOrPostError(mFd, mMdatOffset, SEEK_SET); seekOrPostError(mFd, mMdatOffset, SEEK_SET); write("\x00\x00\x00\x01mdat????????", 16); write("\x00\x00\x00\x01mdat????????", 16); status_t err = startWriterThread(); /* Confirm whether the writing of the initial file atoms, ftyp and free, if (err != OK) { * are written to the file properly by posting kWhatNoIOErrorSoFar to the return err; * MP4WtrCtrlHlpLooper that's handling write and seek errors also. If there } * was kWhatIOError, the following two scenarios should be handled. * 1) If kWhatIOError was delivered and processed, MP4WtrCtrlHlpLooper setupAndStartLooper(); * would have stopped all threads gracefully already and posting * kWhatNoIOErrorSoFar would fail. int32_t is4bitTrackId = false; * 2) If kWhatIOError wasn't delivered or getting processed, if (param && param->findInt32(kKey4BitTrackIds, &is4bitTrackId) && is4bitTrackId) { * kWhatNoIOErrorSoFar should get posted successfully. Wait for err = validateAllTracksId(true); * response from MP4WtrCtrlHlpLooper. } */ else { sp<AMessage> msg = new AMessage(kWhatNoIOErrorSoFar, mReflector); err = validateAllTracksId(false); sp<AMessage> response; } err = msg->postAndAwaitResponse(&response); if (err != OK) { if (err != OK || !response->findInt32("err", &err) || err != OK) { return err; return ERROR_IO; } } err = startTracks(param); err = startTracks(param); Loading Loading @@ -1025,13 +1045,16 @@ status_t MPEG4Writer::stopWriterThread() { } } void *dummy; void *dummy; status_t err = pthread_join(mThread, &dummy); status_t err = OK; WARN_UNLESS(err == 0, "stopWriterThread pthread_join err: %d", err); int retVal = pthread_join(mThread, &dummy); if (retVal == 0) { err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGD("WriterThread stopped. Status:%d", err); } else { ALOGE("stopWriterThread pthread_join status:%d", retVal); err = UNKNOWN_ERROR; } mWriterThreadStarted = false; mWriterThreadStarted = false; WARN_UNLESS(err == 0, "stopWriterThread pthread_join retVal: %d", err); ALOGD("Writer thread stopped"); return err; return err; } } Loading Loading @@ -1089,23 +1112,26 @@ void MPEG4Writer::writeCompositionMatrix(int degrees) { status_t MPEG4Writer::release() { status_t MPEG4Writer::release() { ALOGD("release()"); ALOGD("release()"); if (mPreAllocationEnabled) { status_t err = OK; truncatePreAllocation(); if (!truncatePreAllocation()) { } if (err == OK) { err = ERROR_IO; } int err = OK; } int retVal = fsync(mFd); if (fsync(mFd) != 0) { WARN_UNLESS(retVal == 0, "fsync err:%s(%d)", std::strerror(errno), errno); ALOGW("(ignored)fsync err:%s(%d)", std::strerror(errno), errno); err |= retVal; // Don't bubble up fsync error, b/157291505. retVal = close(mFd); // if (err == OK) { err = ERROR_IO; } WARN_UNLESS(retVal == 0, "close err:%s(%d)", std::strerror(errno), errno); } err |= retVal; if (close(mFd) != 0) { ALOGE("close err:%s(%d)", std::strerror(errno), errno); if (err == OK) { err = ERROR_IO; } } mFd = -1; mFd = -1; if (mNextFd != -1) { if (mNextFd != -1) { retVal = close(mNextFd); if (close(mNextFd) != 0) { ALOGE("close(mNextFd) error:%s(%d)", std::strerror(errno), errno); } if (err == OK) { err = ERROR_IO; } mNextFd = -1; mNextFd = -1; WARN_UNLESS(retVal == 0, "close mNextFd error:%s(%d)", std::strerror(errno), errno); err |= retVal; } } stopAndReleaseLooper(); stopAndReleaseLooper(); mInitCheck = NO_INIT; mInitCheck = NO_INIT; Loading Loading @@ -1165,7 +1191,7 @@ status_t MPEG4Writer::reset(bool stopSource) { for (List<Track *>::iterator it = mTracks.begin(); for (List<Track *>::iterator it = mTracks.begin(); it != mTracks.end(); ++it) { it != mTracks.end(); ++it) { status_t trackErr = (*it)->stop(stopSource); status_t trackErr = (*it)->stop(stopSource); WARN_UNLESS(trackErr == 0, "%s track stopped with an error", WARN_UNLESS(trackErr == OK, "%s track stopped with an error", (*it)->getTrackType()); (*it)->getTrackType()); if (err == OK && trackErr != OK) { if (err == OK && trackErr != OK) { err = trackErr; err = trackErr; Loading Loading @@ -1254,7 +1280,11 @@ status_t MPEG4Writer::reset(bool stopSource) { CHECK(mBoxes.empty()); CHECK(mBoxes.empty()); err = release(); status_t errRelease = release(); // Prioritize the error that occurred before release(). if (err == OK) { err = errRelease; } return err; return err; } } Loading Loading @@ -1577,9 +1607,8 @@ void MPEG4Writer::writeOrPostError(int fd, const void* buf, size_t count) { // Can't guarantee that file is usable or write would succeed anymore, hence signal to stop. // Can't guarantee that file is usable or write would succeed anymore, hence signal to stop. sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); msg->setInt32("errno", errno); msg->setInt32("err", ERROR_IO); status_t err = msg->post(); WARN_UNLESS(msg->post() == OK, "writeOrPostError:error posting ERROR_IO"); ALOGE("writeOrPostError post:%d", err); } } void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) { void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) { Loading @@ -1597,9 +1626,8 @@ void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) { // Can't guarantee that file is usable or seek would succeed anymore, hence signal to stop. // Can't guarantee that file is usable or seek would succeed anymore, hence signal to stop. sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); sp<AMessage> msg = new AMessage(kWhatIOError, mReflector); msg->setInt32("errno", errno); msg->setInt32("err", ERROR_IO); status_t err = msg->post(); WARN_UNLESS(msg->post() == OK, "seekOrPostError:error posting ERROR_IO"); ALOGE("seekOrPostError post:%d", err); } } void MPEG4Writer::beginBox(uint32_t id) { void MPEG4Writer::beginBox(uint32_t id) { Loading Loading @@ -1838,7 +1866,7 @@ bool MPEG4Writer::preAllocate(uint64_t wantSize) { if (res == -1) { if (res == -1) { ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd); ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd); sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector); sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector); msg->setInt32("errno", errno); msg->setInt32("err", ERROR_IO); status_t err = msg->post(); status_t err = msg->post(); mFallocateErr = true; mFallocateErr = true; ALOGD("preAllocation post:%d", err); ALOGD("preAllocation post:%d", err); Loading @@ -1850,6 +1878,9 @@ bool MPEG4Writer::preAllocate(uint64_t wantSize) { } } bool MPEG4Writer::truncatePreAllocation() { bool MPEG4Writer::truncatePreAllocation() { if (!mPreAllocationEnabled) return true; bool status = true; bool status = true; off64_t endOffset = std::max(mMdatEndOffset, mOffset); off64_t endOffset = std::max(mMdatEndOffset, mOffset); /* if mPreAllocateFileEndOffset >= endOffset, then preallocation logic works good. (diff >= 0). /* if mPreAllocateFileEndOffset >= endOffset, then preallocation logic works good. (diff >= 0). Loading @@ -1861,6 +1892,10 @@ bool MPEG4Writer::truncatePreAllocation() { if(ftruncate(mFd, endOffset) == -1) { if(ftruncate(mFd, endOffset) == -1) { ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd); ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd); status = false; status = false; /* No need to post and handle(stop & notify client) error like it's done in preAllocate(), * because ftruncate() is called during release() only and the error here would be * reported from there as this function is returning false on any error in ftruncate(). */ } } return status; return status; } } Loading Loading @@ -2153,14 +2188,17 @@ void MPEG4Writer::Track::addOneElstTableEntry( mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction)); mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction)); } } void MPEG4Writer::setupAndStartLooper() { status_t MPEG4Writer::setupAndStartLooper() { status_t err = OK; if (mLooper == nullptr) { if (mLooper == nullptr) { mLooper = new ALooper; mLooper = new ALooper; mLooper->setName("MP4WtrCtrlHlpLooper"); mLooper->setName("MP4WtrCtrlHlpLooper"); mLooper->start(); err = mLooper->start(); mReflector = new AHandlerReflector<MPEG4Writer>(this); mReflector = new AHandlerReflector<MPEG4Writer>(this); mLooper->registerHandler(mReflector); mLooper->registerHandler(mReflector); } } ALOGD("MP4WtrCtrlHlpLooper Started"); return err; } } void MPEG4Writer::stopAndReleaseLooper() { void MPEG4Writer::stopAndReleaseLooper() { Loading Loading @@ -2399,23 +2437,35 @@ void MPEG4Writer::onMessageReceived(const sp<AMessage> &msg) { case kWhatIOError: { case kWhatIOError: { ALOGE("kWhatIOError"); ALOGE("kWhatIOError"); int32_t err; int32_t err; CHECK(msg->findInt32("errno", &err)); CHECK(msg->findInt32("err", &err)); // Stop tracks' threads and main writer thread. // Stop tracks' threads and main writer thread. stop(); stop(); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); break; break; } } // fallocate() failed, hence notify app about it and stop(). // fallocate() failed, hence stop() and notify app. case kWhatFallocateError: { case kWhatFallocateError: { ALOGE("kWhatFallocateError"); ALOGE("kWhatFallocateError"); int32_t err; int32_t err; CHECK(msg->findInt32("errno", &err)); CHECK(msg->findInt32("err", &err)); // Stop tracks' threads and main writer thread. // Stop tracks' threads and main writer thread. stop(); stop(); //TODO: introduce a suitable MEDIA_RECORDER_ERROR_* instead MEDIA_RECORDER_ERROR_UNKNOWN? //TODO: introduce a suitable MEDIA_RECORDER_ERROR_* instead MEDIA_RECORDER_ERROR_UNKNOWN? notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err); break; break; } } /* Response to kWhatNoIOErrorSoFar would be OK always as of now. * Responding with other options could be added later if required. */ case kWhatNoIOErrorSoFar: { ALOGD("kWhatNoIOErrorSoFar"); sp<AMessage> response = new AMessage; response->setInt32("err", OK); sp<AReplyToken> replyID; CHECK(msg->senderAwaitsResponse(&replyID)); response->postReply(replyID); break; } default: default: TRESPASS(); TRESPASS(); } } Loading Loading @@ -2778,11 +2828,16 @@ status_t MPEG4Writer::Track::stop(bool stopSource) { mDone = true; mDone = true; void *dummy; void *dummy; status_t err = pthread_join(mThread, &dummy); status_t err = OK; WARN_UNLESS(err == 0, "track::stop: pthread_join status:%d", err); int retVal = pthread_join(mThread, &dummy); status_t threadRetVal = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); if (retVal == 0) { WARN_UNLESS(threadRetVal == 0, "%s track stopped. Status :%d. %s source", err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGD("%s track stopped. Status:%d. %s source", getTrackType(), err, stopSource ? "Stop" : "Not Stop"); getTrackType(), err, stopSource ? "Stop" : "Not Stop"); } else { ALOGE("track::stop: pthread_join retVal:%d", retVal); err = UNKNOWN_ERROR; } mStarted = false; mStarted = false; return err; return err; } } Loading
media/libstagefright/include/media/stagefright/MPEG4Writer.h +3 −2 Original line number Original line Diff line number Diff line Loading @@ -87,7 +87,8 @@ private: enum { enum { kWhatSwitch = 'swch', kWhatSwitch = 'swch', kWhatIOError = 'ioer', kWhatIOError = 'ioer', kWhatFallocateError = 'faer' kWhatFallocateError = 'faer', kWhatNoIOErrorSoFar = 'noie' }; }; int mFd; int mFd; Loading Loading @@ -231,7 +232,7 @@ private: status_t stopWriterThread(); status_t stopWriterThread(); static void *ThreadWrapper(void *me); static void *ThreadWrapper(void *me); void threadFunc(); void threadFunc(); void setupAndStartLooper(); status_t setupAndStartLooper(); void stopAndReleaseLooper(); void stopAndReleaseLooper(); // Buffer a single chunk to be written out later. // Buffer a single chunk to be written out later. Loading