Loading include/media/stagefright/MediaCodecSource.h +0 −4 Original line number Diff line number Diff line Loading @@ -85,8 +85,6 @@ private: status_t initEncoder(); void releaseEncoder(); status_t feedEncoderInputBuffers(); void scheduleDoMoreWork(); status_t doMoreWork(int32_t numInput, int32_t numOutput); void suspend(); void resume(int64_t skipFramesBeforeUs = -1ll); void signalEOS(status_t err = ERROR_END_OF_STREAM); Loading @@ -108,8 +106,6 @@ private: bool mDoMoreWorkPending; sp<AMessage> mEncoderActivityNotify; sp<IGraphicBufferProducer> mGraphicBufferProducer; Vector<sp<ABuffer> > mEncoderInputBuffers; Vector<sp<ABuffer> > mEncoderOutputBuffers; List<MediaBuffer *> mInputBufferQueue; List<size_t> mAvailEncoderInputIndices; List<int64_t> mDecodingTimeQueue; // decoding time (us) for video Loading media/libstagefright/MediaCodecSource.cpp +105 −164 Original line number Diff line number Diff line Loading @@ -422,19 +422,11 @@ status_t MediaCodecSource::initEncoder() { } } err = mEncoder->start(); if (err != OK) { return err; } err = mEncoder->getInputBuffers(&mEncoderInputBuffers); if (err != OK) { return err; } mEncoderActivityNotify = new AMessage( kWhatEncoderActivity, mReflector->id()); mEncoder->setCallback(mEncoderActivityNotify); err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers); err = mEncoder->start(); if (err != OK) { return err; Loading @@ -461,14 +453,6 @@ void MediaCodecSource::releaseEncoder() { mbuf->release(); } } for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) { sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i); accessUnit->setMediaBufferBase(NULL); } mEncoderInputBuffers.clear(); mEncoderOutputBuffers.clear(); } status_t MediaCodecSource::postSynchronouslyAndReturnError( Loading Loading @@ -539,20 +523,6 @@ void MediaCodecSource::resume(int64_t skipFramesBeforeUs) { } } void MediaCodecSource::scheduleDoMoreWork() { if (mDoMoreWorkPending) { return; } mDoMoreWorkPending = true; if (mEncoderActivityNotify == NULL) { mEncoderActivityNotify = new AMessage( kWhatEncoderActivity, mReflector->id()); } mEncoder->requestActivityNotification(mEncoderActivityNotify); } status_t MediaCodecSource::feedEncoderInputBuffers() { while (!mInputBufferQueue.empty() && !mAvailEncoderInputIndices.empty()) { Loading Loading @@ -587,16 +557,22 @@ status_t MediaCodecSource::feedEncoderInputBuffers() { #endif // DEBUG_DRIFT_TIME } sp<ABuffer> inbuf; status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf); if (err != OK || inbuf == NULL) { mbuf->release(); signalEOS(); break; } size = mbuf->size(); memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(), mbuf->data(), size); memcpy(inbuf->data(), mbuf->data(), size); if (mIsVideo) { // video encoder will release MediaBuffer when done // with underlying data. mEncoderInputBuffers.itemAt(bufferIndex)->setMediaBufferBase( mbuf); inbuf->setMediaBufferBase(mbuf); } else { mbuf->release(); } Loading @@ -615,113 +591,6 @@ status_t MediaCodecSource::feedEncoderInputBuffers() { return OK; } status_t MediaCodecSource::doMoreWork(int32_t numInput, int32_t numOutput) { status_t err = OK; if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { while (numInput-- > 0) { size_t bufferIndex; err = mEncoder->dequeueInputBuffer(&bufferIndex); if (err != OK) { break; } mAvailEncoderInputIndices.push_back(bufferIndex); } feedEncoderInputBuffers(); } while (numOutput-- > 0) { size_t bufferIndex; size_t offset; size_t size; int64_t timeUs; uint32_t flags; native_handle_t* handle = NULL; err = mEncoder->dequeueOutputBuffer( &bufferIndex, &offset, &size, &timeUs, &flags); if (err != OK) { if (err == INFO_FORMAT_CHANGED) { continue; } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { mEncoder->getOutputBuffers(&mEncoderOutputBuffers); continue; } if (err == -EAGAIN) { err = OK; } break; } if (!(flags & MediaCodec::BUFFER_FLAG_EOS)) { sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex); MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); memcpy(mbuf->data(), outbuf->data(), outbuf->size()); if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { if (mIsVideo) { int64_t decodingTimeUs; if (mFlags & FLAG_USE_SURFACE_INPUT) { // GraphicBufferSource is supposed to discard samples // queued before start, and offset timeUs by start time CHECK_GE(timeUs, 0ll); // TODO: // Decoding time for surface source is unavailable, // use presentation time for now. May need to move // this logic into MediaCodec. decodingTimeUs = timeUs; } else { CHECK(!mDecodingTimeQueue.empty()); decodingTimeUs = *(mDecodingTimeQueue.begin()); mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); } mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, timeUs, timeUs / 1E6, decodingTimeUs - timeUs); } else { int64_t driftTimeUs = 0; #if DEBUG_DRIFT_TIME CHECK(!mDriftTimeQueue.empty()); driftTimeUs = *(mDriftTimeQueue.begin()); mDriftTimeQueue.erase(mDriftTimeQueue.begin()); mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); #endif // DEBUG_DRIFT_TIME ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, timeUs, timeUs / 1E6, driftTimeUs); } mbuf->meta_data()->setInt64(kKeyTime, timeUs); } else { mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); } if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); } mbuf->setObserver(this); mbuf->add_ref(); { Mutex::Autolock autoLock(mOutputBufferLock); mOutputBufferQueue.push_back(mbuf); mOutputBufferCond.signal(); } } mEncoder->releaseOutputBuffer(bufferIndex); if (flags & MediaCodec::BUFFER_FLAG_EOS) { err = ERROR_END_OF_STREAM; break; } } return err; } status_t MediaCodecSource::onStart(MetaData *params) { if (mStopping) { ALOGE("Failed to start while we're stopping"); Loading Loading @@ -749,7 +618,6 @@ status_t MediaCodecSource::onStart(MetaData *params) { startTimeUs = -1ll; } resume(startTimeUs); scheduleDoMoreWork(); } else { CHECK(mPuller != NULL); sp<AMessage> notify = new AMessage( Loading Loading @@ -793,36 +661,109 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { mInputBufferQueue.push_back(mbuf); feedEncoderInputBuffers(); scheduleDoMoreWork(); break; } case kWhatEncoderActivity: { mDoMoreWorkPending = false; if (mEncoder == NULL) { break; } int32_t numInput, numOutput; int32_t cbID; CHECK(msg->findInt32("callbackID", &cbID)); if (cbID == MediaCodec::CB_INPUT_AVAILABLE) { int32_t index; CHECK(msg->findInt32("index", &index)); mAvailEncoderInputIndices.push_back(index); feedEncoderInputBuffers(); } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) { int32_t index; size_t offset; size_t size; int64_t timeUs; int32_t flags; native_handle_t* handle = NULL; CHECK(msg->findInt32("index", &index)); CHECK(msg->findSize("offset", &offset)); CHECK(msg->findSize("size", &size)); CHECK(msg->findInt64("timeUs", &timeUs)); CHECK(msg->findInt32("flags", &flags)); if (!msg->findInt32("input-buffers", &numInput)) { numInput = INT32_MAX; if (flags & MediaCodec::BUFFER_FLAG_EOS) { mEncoder->releaseOutputBuffer(index); signalEOS(); break; } if (!msg->findInt32("output-buffers", &numOutput)) { numOutput = INT32_MAX; sp<ABuffer> outbuf; status_t err = mEncoder->getOutputBuffer(index, &outbuf); if (err != OK || outbuf == NULL) { signalEOS(); break; } status_t err = doMoreWork(numInput, numOutput); MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); memcpy(mbuf->data(), outbuf->data(), outbuf->size()); if (err == OK) { scheduleDoMoreWork(); if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { if (mIsVideo) { int64_t decodingTimeUs; if (mFlags & FLAG_USE_SURFACE_INPUT) { // GraphicBufferSource is supposed to discard samples // queued before start, and offset timeUs by start time CHECK_GE(timeUs, 0ll); // TODO: // Decoding time for surface source is unavailable, // use presentation time for now. May need to move // this logic into MediaCodec. decodingTimeUs = timeUs; } else { // reached EOS, or error signalEOS(err); CHECK(!mDecodingTimeQueue.empty()); decodingTimeUs = *(mDecodingTimeQueue.begin()); mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); } mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, timeUs, timeUs / 1E6, decodingTimeUs - timeUs); } else { int64_t driftTimeUs = 0; #if DEBUG_DRIFT_TIME CHECK(!mDriftTimeQueue.empty()); driftTimeUs = *(mDriftTimeQueue.begin()); mDriftTimeQueue.erase(mDriftTimeQueue.begin()); mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); #endif // DEBUG_DRIFT_TIME ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, timeUs, timeUs / 1E6, driftTimeUs); } mbuf->meta_data()->setInt64(kKeyTime, timeUs); } else { mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); } if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); } mbuf->setObserver(this); mbuf->add_ref(); { Mutex::Autolock autoLock(mOutputBufferLock); mOutputBufferQueue.push_back(mbuf); mOutputBufferCond.signal(); } mEncoder->releaseOutputBuffer(index); } else if (cbID == MediaCodec::CB_ERROR) { status_t err; CHECK(msg->findInt32("err", &err)); ALOGE("Encoder (%s) reported error : 0x%x", mIsVideo ? "video" : "audio", err); signalEOS(); } break; } case kWhatStart: Loading Loading
include/media/stagefright/MediaCodecSource.h +0 −4 Original line number Diff line number Diff line Loading @@ -85,8 +85,6 @@ private: status_t initEncoder(); void releaseEncoder(); status_t feedEncoderInputBuffers(); void scheduleDoMoreWork(); status_t doMoreWork(int32_t numInput, int32_t numOutput); void suspend(); void resume(int64_t skipFramesBeforeUs = -1ll); void signalEOS(status_t err = ERROR_END_OF_STREAM); Loading @@ -108,8 +106,6 @@ private: bool mDoMoreWorkPending; sp<AMessage> mEncoderActivityNotify; sp<IGraphicBufferProducer> mGraphicBufferProducer; Vector<sp<ABuffer> > mEncoderInputBuffers; Vector<sp<ABuffer> > mEncoderOutputBuffers; List<MediaBuffer *> mInputBufferQueue; List<size_t> mAvailEncoderInputIndices; List<int64_t> mDecodingTimeQueue; // decoding time (us) for video Loading
media/libstagefright/MediaCodecSource.cpp +105 −164 Original line number Diff line number Diff line Loading @@ -422,19 +422,11 @@ status_t MediaCodecSource::initEncoder() { } } err = mEncoder->start(); if (err != OK) { return err; } err = mEncoder->getInputBuffers(&mEncoderInputBuffers); if (err != OK) { return err; } mEncoderActivityNotify = new AMessage( kWhatEncoderActivity, mReflector->id()); mEncoder->setCallback(mEncoderActivityNotify); err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers); err = mEncoder->start(); if (err != OK) { return err; Loading @@ -461,14 +453,6 @@ void MediaCodecSource::releaseEncoder() { mbuf->release(); } } for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) { sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i); accessUnit->setMediaBufferBase(NULL); } mEncoderInputBuffers.clear(); mEncoderOutputBuffers.clear(); } status_t MediaCodecSource::postSynchronouslyAndReturnError( Loading Loading @@ -539,20 +523,6 @@ void MediaCodecSource::resume(int64_t skipFramesBeforeUs) { } } void MediaCodecSource::scheduleDoMoreWork() { if (mDoMoreWorkPending) { return; } mDoMoreWorkPending = true; if (mEncoderActivityNotify == NULL) { mEncoderActivityNotify = new AMessage( kWhatEncoderActivity, mReflector->id()); } mEncoder->requestActivityNotification(mEncoderActivityNotify); } status_t MediaCodecSource::feedEncoderInputBuffers() { while (!mInputBufferQueue.empty() && !mAvailEncoderInputIndices.empty()) { Loading Loading @@ -587,16 +557,22 @@ status_t MediaCodecSource::feedEncoderInputBuffers() { #endif // DEBUG_DRIFT_TIME } sp<ABuffer> inbuf; status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf); if (err != OK || inbuf == NULL) { mbuf->release(); signalEOS(); break; } size = mbuf->size(); memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(), mbuf->data(), size); memcpy(inbuf->data(), mbuf->data(), size); if (mIsVideo) { // video encoder will release MediaBuffer when done // with underlying data. mEncoderInputBuffers.itemAt(bufferIndex)->setMediaBufferBase( mbuf); inbuf->setMediaBufferBase(mbuf); } else { mbuf->release(); } Loading @@ -615,113 +591,6 @@ status_t MediaCodecSource::feedEncoderInputBuffers() { return OK; } status_t MediaCodecSource::doMoreWork(int32_t numInput, int32_t numOutput) { status_t err = OK; if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { while (numInput-- > 0) { size_t bufferIndex; err = mEncoder->dequeueInputBuffer(&bufferIndex); if (err != OK) { break; } mAvailEncoderInputIndices.push_back(bufferIndex); } feedEncoderInputBuffers(); } while (numOutput-- > 0) { size_t bufferIndex; size_t offset; size_t size; int64_t timeUs; uint32_t flags; native_handle_t* handle = NULL; err = mEncoder->dequeueOutputBuffer( &bufferIndex, &offset, &size, &timeUs, &flags); if (err != OK) { if (err == INFO_FORMAT_CHANGED) { continue; } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { mEncoder->getOutputBuffers(&mEncoderOutputBuffers); continue; } if (err == -EAGAIN) { err = OK; } break; } if (!(flags & MediaCodec::BUFFER_FLAG_EOS)) { sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex); MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); memcpy(mbuf->data(), outbuf->data(), outbuf->size()); if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { if (mIsVideo) { int64_t decodingTimeUs; if (mFlags & FLAG_USE_SURFACE_INPUT) { // GraphicBufferSource is supposed to discard samples // queued before start, and offset timeUs by start time CHECK_GE(timeUs, 0ll); // TODO: // Decoding time for surface source is unavailable, // use presentation time for now. May need to move // this logic into MediaCodec. decodingTimeUs = timeUs; } else { CHECK(!mDecodingTimeQueue.empty()); decodingTimeUs = *(mDecodingTimeQueue.begin()); mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); } mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, timeUs, timeUs / 1E6, decodingTimeUs - timeUs); } else { int64_t driftTimeUs = 0; #if DEBUG_DRIFT_TIME CHECK(!mDriftTimeQueue.empty()); driftTimeUs = *(mDriftTimeQueue.begin()); mDriftTimeQueue.erase(mDriftTimeQueue.begin()); mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); #endif // DEBUG_DRIFT_TIME ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, timeUs, timeUs / 1E6, driftTimeUs); } mbuf->meta_data()->setInt64(kKeyTime, timeUs); } else { mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); } if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); } mbuf->setObserver(this); mbuf->add_ref(); { Mutex::Autolock autoLock(mOutputBufferLock); mOutputBufferQueue.push_back(mbuf); mOutputBufferCond.signal(); } } mEncoder->releaseOutputBuffer(bufferIndex); if (flags & MediaCodec::BUFFER_FLAG_EOS) { err = ERROR_END_OF_STREAM; break; } } return err; } status_t MediaCodecSource::onStart(MetaData *params) { if (mStopping) { ALOGE("Failed to start while we're stopping"); Loading Loading @@ -749,7 +618,6 @@ status_t MediaCodecSource::onStart(MetaData *params) { startTimeUs = -1ll; } resume(startTimeUs); scheduleDoMoreWork(); } else { CHECK(mPuller != NULL); sp<AMessage> notify = new AMessage( Loading Loading @@ -793,36 +661,109 @@ void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { mInputBufferQueue.push_back(mbuf); feedEncoderInputBuffers(); scheduleDoMoreWork(); break; } case kWhatEncoderActivity: { mDoMoreWorkPending = false; if (mEncoder == NULL) { break; } int32_t numInput, numOutput; int32_t cbID; CHECK(msg->findInt32("callbackID", &cbID)); if (cbID == MediaCodec::CB_INPUT_AVAILABLE) { int32_t index; CHECK(msg->findInt32("index", &index)); mAvailEncoderInputIndices.push_back(index); feedEncoderInputBuffers(); } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) { int32_t index; size_t offset; size_t size; int64_t timeUs; int32_t flags; native_handle_t* handle = NULL; CHECK(msg->findInt32("index", &index)); CHECK(msg->findSize("offset", &offset)); CHECK(msg->findSize("size", &size)); CHECK(msg->findInt64("timeUs", &timeUs)); CHECK(msg->findInt32("flags", &flags)); if (!msg->findInt32("input-buffers", &numInput)) { numInput = INT32_MAX; if (flags & MediaCodec::BUFFER_FLAG_EOS) { mEncoder->releaseOutputBuffer(index); signalEOS(); break; } if (!msg->findInt32("output-buffers", &numOutput)) { numOutput = INT32_MAX; sp<ABuffer> outbuf; status_t err = mEncoder->getOutputBuffer(index, &outbuf); if (err != OK || outbuf == NULL) { signalEOS(); break; } status_t err = doMoreWork(numInput, numOutput); MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); memcpy(mbuf->data(), outbuf->data(), outbuf->size()); if (err == OK) { scheduleDoMoreWork(); if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { if (mIsVideo) { int64_t decodingTimeUs; if (mFlags & FLAG_USE_SURFACE_INPUT) { // GraphicBufferSource is supposed to discard samples // queued before start, and offset timeUs by start time CHECK_GE(timeUs, 0ll); // TODO: // Decoding time for surface source is unavailable, // use presentation time for now. May need to move // this logic into MediaCodec. decodingTimeUs = timeUs; } else { // reached EOS, or error signalEOS(err); CHECK(!mDecodingTimeQueue.empty()); decodingTimeUs = *(mDecodingTimeQueue.begin()); mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); } mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, timeUs, timeUs / 1E6, decodingTimeUs - timeUs); } else { int64_t driftTimeUs = 0; #if DEBUG_DRIFT_TIME CHECK(!mDriftTimeQueue.empty()); driftTimeUs = *(mDriftTimeQueue.begin()); mDriftTimeQueue.erase(mDriftTimeQueue.begin()); mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); #endif // DEBUG_DRIFT_TIME ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, timeUs, timeUs / 1E6, driftTimeUs); } mbuf->meta_data()->setInt64(kKeyTime, timeUs); } else { mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); } if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); } mbuf->setObserver(this); mbuf->add_ref(); { Mutex::Autolock autoLock(mOutputBufferLock); mOutputBufferQueue.push_back(mbuf); mOutputBufferCond.signal(); } mEncoder->releaseOutputBuffer(index); } else if (cbID == MediaCodec::CB_ERROR) { status_t err; CHECK(msg->findInt32("err", &err)); ALOGE("Encoder (%s) reported error : 0x%x", mIsVideo ? "video" : "audio", err); signalEOS(); } break; } case kWhatStart: Loading