Loading cmds/screenrecord/screenrecord.cpp +29 −5 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ static bool gMonotonicTime = false; // use system monotonic time for timesta static enum { FORMAT_MP4, FORMAT_H264, FORMAT_FRAMES, FORMAT_RAW_FRAMES } gOutputFormat = FORMAT_MP4; // data format for output static AString gCodecName = ""; // codec name override static bool gSizeSpecified = false; // was size explicitly requested? static bool gWantInfoScreen = false; // do we want initial info screen? static bool gWantFrameTime = false; // do we want times on each frame? Loading Loading @@ -154,6 +155,7 @@ static status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec, if (gVerbose) { printf("Configuring recorder for %dx%d %s at %.2fMbps\n", gVideoWidth, gVideoHeight, kMimeTypeAvc, gBitRate / 1000000.0); fflush(stdout); } sp<AMessage> format = new AMessage; Loading @@ -169,12 +171,22 @@ static status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec, looper->setName("screenrecord_looper"); looper->start(); ALOGV("Creating codec"); sp<MediaCodec> codec = MediaCodec::CreateByType(looper, kMimeTypeAvc, true); sp<MediaCodec> codec; if (gCodecName.empty()) { codec = MediaCodec::CreateByType(looper, kMimeTypeAvc, true); if (codec == NULL) { fprintf(stderr, "ERROR: unable to create %s codec instance\n", kMimeTypeAvc); return UNKNOWN_ERROR; } } else { codec = MediaCodec::CreateByComponentName(looper, gCodecName); if (codec == NULL) { fprintf(stderr, "ERROR: unable to create %s codec instance\n", gCodecName.c_str()); return UNKNOWN_ERROR; } } err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE); Loading Loading @@ -275,9 +287,11 @@ static status_t setDisplayProjection( if (gRotate) { printf("Rotated content area is %ux%u at offset x=%d y=%d\n", outHeight, outWidth, offY, offX); fflush(stdout); } else { printf("Content area is %ux%u at offset x=%d y=%d\n", outWidth, outHeight, offX, offY); fflush(stdout); } } Loading Loading @@ -346,6 +360,7 @@ static status_t runEncoder(const sp<MediaCodec>& encoder, if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) { if (gVerbose) { printf("Time limit reached\n"); fflush(stdout); } break; } Loading Loading @@ -483,6 +498,7 @@ static status_t runEncoder(const sp<MediaCodec>& encoder, printf("Encoder stopping; recorded %u frames in %" PRId64 " seconds\n", debugNumFrames, nanoseconds_to_seconds( systemTime(CLOCK_MONOTONIC) - startWhenNsec)); fflush(stdout); } return NO_ERROR; } Loading Loading @@ -556,6 +572,7 @@ static status_t recordScreen(const char* fileName) { printf("Main display is %dx%d @%.2ffps (orientation=%u)\n", mainDpyInfo.w, mainDpyInfo.h, mainDpyInfo.fps, mainDpyInfo.orientation); fflush(stdout); } bool rotated = isDeviceRotated(mainDpyInfo.orientation); Loading Loading @@ -623,6 +640,7 @@ static status_t recordScreen(const char* fileName) { } if (gVerbose) { printf("Bugreport overlay created\n"); fflush(stdout); } } else { // Use the encoder's input surface as the virtual display surface. Loading Loading @@ -715,6 +733,7 @@ static status_t recordScreen(const char* fileName) { if (gVerbose) { printf("Stopping encoder and muxer\n"); fflush(stdout); } } Loading Loading @@ -761,6 +780,7 @@ static status_t notifyMediaScanner(const char* fileName) { printf(" %s", argv[i]); } putchar('\n'); fflush(stdout); } pid_t pid = fork(); Loading Loading @@ -898,6 +918,7 @@ int main(int argc, char* const argv[]) { { "show-frame-time", no_argument, NULL, 'f' }, { "rotate", no_argument, NULL, 'r' }, { "output-format", required_argument, NULL, 'o' }, { "codec-name", required_argument, NULL, 'N' }, { "monotonic-time", no_argument, NULL, 'm' }, { NULL, 0, NULL, 0 } }; Loading Loading @@ -978,6 +999,9 @@ int main(int argc, char* const argv[]) { return 2; } break; case 'N': gCodecName = optarg; break; case 'm': gMonotonicTime = true; break; Loading media/libstagefright/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ cc_library_shared { "libmedia_helper", "libstagefright_codec2", "libstagefright_foundation", "libstagefright_gbs", "libstagefright_omx", "libstagefright_omx_utils", "libstagefright_xmlparser", Loading media/libstagefright/CCodec.cpp +154 −59 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ #include <C2PlatformSupport.h> #include <gui/Surface.h> #include <media/stagefright/BufferProducerWrapper.h> #include <media/stagefright/CCodec.h> #include <media/stagefright/PersistentSurface.h> #include "include/CCodecBufferChannel.h" Loading Loading @@ -111,15 +113,17 @@ Mutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance; class CCodecListener : public C2Component::Listener { public: CCodecListener(const std::shared_ptr<CCodecBufferChannel> &channel) : mChannel(channel) { } explicit CCodecListener(const wp<CCodec> &codec) : mCodec(codec) {} virtual void onWorkDone_nb( std::weak_ptr<C2Component> component, std::vector<std::unique_ptr<C2Work>> workItems) override { (void)component; mChannel->onWorkDone(std::move(workItems)); sp<CCodec> codec(mCodec.promote()); if (!codec) { return; } codec->onWorkDone(workItems); } virtual void onTripped_nb( Loading @@ -137,7 +141,7 @@ public: } private: std::shared_ptr<CCodecBufferChannel> mChannel; wp<CCodec> mCodec; }; } // namespace Loading @@ -159,11 +163,11 @@ std::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() { void CCodec::initiateAllocateComponent(const sp<AMessage> &msg) { { Mutexed<State>::Locked state(mState); if (state->mState != RELEASED) { if (state->get() != RELEASED) { mCallback->onError(INVALID_OPERATION, ACTION_CODE_FATAL); return; } state->mState = ALLOCATING; state->set(ALLOCATING); } AString componentName; Loading @@ -178,14 +182,14 @@ void CCodec::initiateAllocateComponent(const sp<AMessage> &msg) { void CCodec::allocate(const AString &componentName) { // TODO: use C2ComponentStore to create component mListener.reset(new CCodecListener(mChannel)); mListener.reset(new CCodecListener(this)); std::shared_ptr<C2Component> comp; c2_status_t err = GetCodec2PlatformComponentStore()->createComponent( componentName.c_str(), &comp); if (err != C2_OK) { Mutexed<State>::Locked state(mState); state->mState = RELEASED; state->set(RELEASED); state.unlock(); mCallback->onError(err, ACTION_CODE_FATAL); state.lock(); Loading @@ -194,15 +198,15 @@ void CCodec::allocate(const AString &componentName) { comp->setListener_vb(mListener, C2_MAY_BLOCK); { Mutexed<State>::Locked state(mState); if (state->mState != ALLOCATING) { state->mState = RELEASED; if (state->get() != ALLOCATING) { state->set(RELEASED); state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = ALLOCATED; state->mComp = comp; state->set(ALLOCATED); state->comp = comp; } mChannel->setComponent(comp); mCallback->onComponentAllocated(comp->intf()->getName().c_str()); Loading @@ -211,7 +215,7 @@ void CCodec::allocate(const AString &componentName) { void CCodec::initiateConfigureComponent(const sp<AMessage> &format) { { Mutexed<State>::Locked state(mState); if (state->mState != ALLOCATED) { if (state->get() != ALLOCATED) { mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); return; } Loading Loading @@ -252,6 +256,9 @@ void CCodec::configure(const sp<AMessage> &msg) { inputFormat->setInt32("sample-rate", 44100); outputFormat->setInt32("channel-count", 1); outputFormat->setInt32("sample-rate", 44100); } else { outputFormat->setInt32("width", 1080); outputFormat->setInt32("height", 1920); } } else { inputFormat->setString("mime", mime); Loading @@ -272,32 +279,81 @@ void CCodec::configure(const sp<AMessage> &msg) { { Mutexed<Formats>::Locked formats(mFormats); formats->mInputFormat = inputFormat; formats->mOutputFormat = outputFormat; formats->inputFormat = inputFormat; formats->outputFormat = outputFormat; } mCallback->onComponentConfigured(inputFormat, outputFormat); } void CCodec::initiateCreateInputSurface() { // TODO (new AMessage(kWhatCreateInputSurface, this))->post(); } void CCodec::createInputSurface() { sp<IGraphicBufferProducer> producer; sp<GraphicBufferSource> source(new GraphicBufferSource); status_t err = source->initCheck(); if (err != OK) { ALOGE("Failed to initialize graphic buffer source: %d", err); mCallback->onInputSurfaceCreationFailed(err); return; } producer = source->getIGraphicBufferProducer(); err = setupInputSurface(source); if (err != OK) { ALOGE("Failed to set up input surface: %d", err); mCallback->onInputSurfaceCreationFailed(err); return; } sp<AMessage> inputFormat; sp<AMessage> outputFormat; { Mutexed<Formats>::Locked formats(mFormats); inputFormat = formats->inputFormat; outputFormat = formats->outputFormat; } mCallback->onInputSurfaceCreated( inputFormat, outputFormat, new BufferProducerWrapper(producer)); } status_t CCodec::setupInputSurface(const sp<GraphicBufferSource> &source) { status_t err = mChannel->setGraphicBufferSource(source); if (err != OK) { return err; } // TODO: configure |source| with other settings. return OK; } void CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) { sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this); msg->setObject("surface", surface); msg->post(); } void CCodec::setInputSurface(const sp<PersistentSurface> &surface) { // TODO (void)surface; mCallback->onInputSurfaceDeclined(ERROR_UNSUPPORTED); } void CCodec::initiateStart() { { Mutexed<State>::Locked state(mState); if (state->mState != ALLOCATED) { if (state->get() != ALLOCATED) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = STARTING; state->set(STARTING); } (new AMessage(kWhatStart, this))->post(); Loading @@ -307,13 +363,13 @@ void CCodec::start() { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState != STARTING) { if (state->get() != STARTING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } comp = state->mComp; comp = state->comp; } c2_status_t err = comp->start(); if (err != C2_OK) { Loading @@ -325,20 +381,20 @@ void CCodec::start() { sp<AMessage> outputFormat; { Mutexed<Formats>::Locked formats(mFormats); inputFormat = formats->mInputFormat; outputFormat = formats->mOutputFormat; inputFormat = formats->inputFormat; outputFormat = formats->outputFormat; } mChannel->start(inputFormat, outputFormat); { Mutexed<State>::Locked state(mState); if (state->mState != STARTING) { if (state->get() != STARTING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = RUNNING; state->set(RUNNING); } mCallback->onStartCompleted(); } Loading @@ -354,17 +410,17 @@ void CCodec::initiateShutdown(bool keepComponentAllocated) { void CCodec::initiateStop() { { Mutexed<State>::Locked state(mState); if (state->mState == ALLOCATED || state->mState == RELEASED || state->mState == STOPPING || state->mState == RELEASING) { if (state->get() == ALLOCATED || state->get() == RELEASED || state->get() == STOPPING || state->get() == RELEASING) { // We're already stopped, released, or doing it right now. state.unlock(); mCallback->onStopCompleted(); state.lock(); return; } state->mState = STOPPING; state->set(STOPPING); } (new AMessage(kWhatStop, this))->post(); Loading @@ -374,19 +430,19 @@ void CCodec::stop() { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState == RELEASING) { if (state->get() == RELEASING) { state.unlock(); // We're already stopped or release is in progress. mCallback->onStopCompleted(); state.lock(); return; } else if (state->mState != STOPPING) { } else if (state->get() != STOPPING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } comp = state->mComp; comp = state->comp; } mChannel->stop(); status_t err = comp->stop(); Loading @@ -397,8 +453,8 @@ void CCodec::stop() { { Mutexed<State>::Locked state(mState); if (state->mState == STOPPING) { state->mState = ALLOCATED; if (state->get() == STOPPING) { state->set(ALLOCATED); } } mCallback->onStopCompleted(); Loading @@ -407,7 +463,7 @@ void CCodec::stop() { void CCodec::initiateRelease(bool sendCallback /* = true */) { { Mutexed<State>::Locked state(mState); if (state->mState == RELEASED || state->mState == RELEASING) { if (state->get() == RELEASED || state->get() == RELEASING) { // We're already released or doing it right now. if (sendCallback) { state.unlock(); Loading @@ -416,8 +472,8 @@ void CCodec::initiateRelease(bool sendCallback /* = true */) { } return; } if (state->mState == ALLOCATING) { state->mState = RELEASING; if (state->get() == ALLOCATING) { state->set(RELEASING); // With the altered state allocate() would fail and clean up. if (sendCallback) { state.unlock(); Loading @@ -426,7 +482,7 @@ void CCodec::initiateRelease(bool sendCallback /* = true */) { } return; } state->mState = RELEASING; state->set(RELEASING); } std::thread([this, sendCallback] { release(sendCallback); }).detach(); Loading @@ -436,7 +492,7 @@ void CCodec::release(bool sendCallback) { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState == RELEASED) { if (state->get() == RELEASED) { if (sendCallback) { state.unlock(); mCallback->onReleaseCompleted(); Loading @@ -444,15 +500,15 @@ void CCodec::release(bool sendCallback) { } return; } comp = state->mComp; comp = state->comp; } mChannel->stop(); comp->release(); { Mutexed<State>::Locked state(mState); state->mState = RELEASED; state->mComp.reset(); state->set(RELEASED); state->comp.reset(); } if (sendCallback) { mCallback->onReleaseCompleted(); Loading @@ -466,11 +522,11 @@ status_t CCodec::setSurface(const sp<Surface> &surface) { void CCodec::signalFlush() { { Mutexed<State>::Locked state(mState); if (state->mState != RUNNING) { if (state->get() != RUNNING) { mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); return; } state->mState = FLUSHING; state->set(FLUSHING); } (new AMessage(kWhatFlush, this))->post(); Loading @@ -480,13 +536,13 @@ void CCodec::flush() { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState != FLUSHING) { if (state->get() != FLUSHING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } comp = state->mComp; comp = state->comp; } mChannel->stop(); Loading @@ -502,7 +558,7 @@ void CCodec::flush() { { Mutexed<State>::Locked state(mState); state->mState = FLUSHED; state->set(FLUSHED); } mCallback->onFlushCompleted(); } Loading @@ -510,26 +566,26 @@ void CCodec::flush() { void CCodec::signalResume() { { Mutexed<State>::Locked state(mState); if (state->mState != FLUSHED) { if (state->get() != FLUSHED) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = RESUMING; state->set(RESUMING); } mChannel->start(nullptr, nullptr); { Mutexed<State>::Locked state(mState); if (state->mState != RESUMING) { if (state->get() != RESUMING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = RUNNING; state->set(RUNNING); } } Loading @@ -545,6 +601,14 @@ void CCodec::signalRequestIDRFrame() { // TODO } void CCodec::onWorkDone(std::vector<std::unique_ptr<C2Work>> &workItems) { Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); for (std::unique_ptr<C2Work> &item : workItems) { queue->push_back(std::move(item)); } (new AMessage(kWhatWorkDone, this))->post(); } void CCodec::onMessageReceived(const sp<AMessage> &msg) { TimePoint now = std::chrono::steady_clock::now(); switch (msg->what()) { Loading Loading @@ -582,6 +646,37 @@ void CCodec::onMessageReceived(const sp<AMessage> &msg) { flush(); break; } case kWhatCreateInputSurface: { // Surface operations may be briefly blocking. setDeadline(now + 100ms); createInputSurface(); break; } case kWhatSetInputSurface: { // Surface operations may be briefly blocking. setDeadline(now + 100ms); sp<RefBase> obj; CHECK(msg->findObject("surface", &obj)); sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get())); setInputSurface(surface); break; } case kWhatWorkDone: { std::unique_ptr<C2Work> work; { Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); if (queue->empty()) { break; } work.swap(queue->front()); queue->pop_front(); if (!queue->empty()) { (new AMessage(kWhatWorkDone, this))->post(); } } mChannel->onWorkDone(work); break; } default: { ALOGE("unrecognized message"); break; Loading Loading
cmds/screenrecord/screenrecord.cpp +29 −5 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ static bool gMonotonicTime = false; // use system monotonic time for timesta static enum { FORMAT_MP4, FORMAT_H264, FORMAT_FRAMES, FORMAT_RAW_FRAMES } gOutputFormat = FORMAT_MP4; // data format for output static AString gCodecName = ""; // codec name override static bool gSizeSpecified = false; // was size explicitly requested? static bool gWantInfoScreen = false; // do we want initial info screen? static bool gWantFrameTime = false; // do we want times on each frame? Loading Loading @@ -154,6 +155,7 @@ static status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec, if (gVerbose) { printf("Configuring recorder for %dx%d %s at %.2fMbps\n", gVideoWidth, gVideoHeight, kMimeTypeAvc, gBitRate / 1000000.0); fflush(stdout); } sp<AMessage> format = new AMessage; Loading @@ -169,12 +171,22 @@ static status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec, looper->setName("screenrecord_looper"); looper->start(); ALOGV("Creating codec"); sp<MediaCodec> codec = MediaCodec::CreateByType(looper, kMimeTypeAvc, true); sp<MediaCodec> codec; if (gCodecName.empty()) { codec = MediaCodec::CreateByType(looper, kMimeTypeAvc, true); if (codec == NULL) { fprintf(stderr, "ERROR: unable to create %s codec instance\n", kMimeTypeAvc); return UNKNOWN_ERROR; } } else { codec = MediaCodec::CreateByComponentName(looper, gCodecName); if (codec == NULL) { fprintf(stderr, "ERROR: unable to create %s codec instance\n", gCodecName.c_str()); return UNKNOWN_ERROR; } } err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE); Loading Loading @@ -275,9 +287,11 @@ static status_t setDisplayProjection( if (gRotate) { printf("Rotated content area is %ux%u at offset x=%d y=%d\n", outHeight, outWidth, offY, offX); fflush(stdout); } else { printf("Content area is %ux%u at offset x=%d y=%d\n", outWidth, outHeight, offX, offY); fflush(stdout); } } Loading Loading @@ -346,6 +360,7 @@ static status_t runEncoder(const sp<MediaCodec>& encoder, if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) { if (gVerbose) { printf("Time limit reached\n"); fflush(stdout); } break; } Loading Loading @@ -483,6 +498,7 @@ static status_t runEncoder(const sp<MediaCodec>& encoder, printf("Encoder stopping; recorded %u frames in %" PRId64 " seconds\n", debugNumFrames, nanoseconds_to_seconds( systemTime(CLOCK_MONOTONIC) - startWhenNsec)); fflush(stdout); } return NO_ERROR; } Loading Loading @@ -556,6 +572,7 @@ static status_t recordScreen(const char* fileName) { printf("Main display is %dx%d @%.2ffps (orientation=%u)\n", mainDpyInfo.w, mainDpyInfo.h, mainDpyInfo.fps, mainDpyInfo.orientation); fflush(stdout); } bool rotated = isDeviceRotated(mainDpyInfo.orientation); Loading Loading @@ -623,6 +640,7 @@ static status_t recordScreen(const char* fileName) { } if (gVerbose) { printf("Bugreport overlay created\n"); fflush(stdout); } } else { // Use the encoder's input surface as the virtual display surface. Loading Loading @@ -715,6 +733,7 @@ static status_t recordScreen(const char* fileName) { if (gVerbose) { printf("Stopping encoder and muxer\n"); fflush(stdout); } } Loading Loading @@ -761,6 +780,7 @@ static status_t notifyMediaScanner(const char* fileName) { printf(" %s", argv[i]); } putchar('\n'); fflush(stdout); } pid_t pid = fork(); Loading Loading @@ -898,6 +918,7 @@ int main(int argc, char* const argv[]) { { "show-frame-time", no_argument, NULL, 'f' }, { "rotate", no_argument, NULL, 'r' }, { "output-format", required_argument, NULL, 'o' }, { "codec-name", required_argument, NULL, 'N' }, { "monotonic-time", no_argument, NULL, 'm' }, { NULL, 0, NULL, 0 } }; Loading Loading @@ -978,6 +999,9 @@ int main(int argc, char* const argv[]) { return 2; } break; case 'N': gCodecName = optarg; break; case 'm': gMonotonicTime = true; break; Loading
media/libstagefright/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ cc_library_shared { "libmedia_helper", "libstagefright_codec2", "libstagefright_foundation", "libstagefright_gbs", "libstagefright_omx", "libstagefright_omx_utils", "libstagefright_xmlparser", Loading
media/libstagefright/CCodec.cpp +154 −59 Original line number Diff line number Diff line Loading @@ -23,7 +23,9 @@ #include <C2PlatformSupport.h> #include <gui/Surface.h> #include <media/stagefright/BufferProducerWrapper.h> #include <media/stagefright/CCodec.h> #include <media/stagefright/PersistentSurface.h> #include "include/CCodecBufferChannel.h" Loading Loading @@ -111,15 +113,17 @@ Mutexed<sp<CCodecWatchdog>> CCodecWatchdog::sInstance; class CCodecListener : public C2Component::Listener { public: CCodecListener(const std::shared_ptr<CCodecBufferChannel> &channel) : mChannel(channel) { } explicit CCodecListener(const wp<CCodec> &codec) : mCodec(codec) {} virtual void onWorkDone_nb( std::weak_ptr<C2Component> component, std::vector<std::unique_ptr<C2Work>> workItems) override { (void)component; mChannel->onWorkDone(std::move(workItems)); sp<CCodec> codec(mCodec.promote()); if (!codec) { return; } codec->onWorkDone(workItems); } virtual void onTripped_nb( Loading @@ -137,7 +141,7 @@ public: } private: std::shared_ptr<CCodecBufferChannel> mChannel; wp<CCodec> mCodec; }; } // namespace Loading @@ -159,11 +163,11 @@ std::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() { void CCodec::initiateAllocateComponent(const sp<AMessage> &msg) { { Mutexed<State>::Locked state(mState); if (state->mState != RELEASED) { if (state->get() != RELEASED) { mCallback->onError(INVALID_OPERATION, ACTION_CODE_FATAL); return; } state->mState = ALLOCATING; state->set(ALLOCATING); } AString componentName; Loading @@ -178,14 +182,14 @@ void CCodec::initiateAllocateComponent(const sp<AMessage> &msg) { void CCodec::allocate(const AString &componentName) { // TODO: use C2ComponentStore to create component mListener.reset(new CCodecListener(mChannel)); mListener.reset(new CCodecListener(this)); std::shared_ptr<C2Component> comp; c2_status_t err = GetCodec2PlatformComponentStore()->createComponent( componentName.c_str(), &comp); if (err != C2_OK) { Mutexed<State>::Locked state(mState); state->mState = RELEASED; state->set(RELEASED); state.unlock(); mCallback->onError(err, ACTION_CODE_FATAL); state.lock(); Loading @@ -194,15 +198,15 @@ void CCodec::allocate(const AString &componentName) { comp->setListener_vb(mListener, C2_MAY_BLOCK); { Mutexed<State>::Locked state(mState); if (state->mState != ALLOCATING) { state->mState = RELEASED; if (state->get() != ALLOCATING) { state->set(RELEASED); state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = ALLOCATED; state->mComp = comp; state->set(ALLOCATED); state->comp = comp; } mChannel->setComponent(comp); mCallback->onComponentAllocated(comp->intf()->getName().c_str()); Loading @@ -211,7 +215,7 @@ void CCodec::allocate(const AString &componentName) { void CCodec::initiateConfigureComponent(const sp<AMessage> &format) { { Mutexed<State>::Locked state(mState); if (state->mState != ALLOCATED) { if (state->get() != ALLOCATED) { mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); return; } Loading Loading @@ -252,6 +256,9 @@ void CCodec::configure(const sp<AMessage> &msg) { inputFormat->setInt32("sample-rate", 44100); outputFormat->setInt32("channel-count", 1); outputFormat->setInt32("sample-rate", 44100); } else { outputFormat->setInt32("width", 1080); outputFormat->setInt32("height", 1920); } } else { inputFormat->setString("mime", mime); Loading @@ -272,32 +279,81 @@ void CCodec::configure(const sp<AMessage> &msg) { { Mutexed<Formats>::Locked formats(mFormats); formats->mInputFormat = inputFormat; formats->mOutputFormat = outputFormat; formats->inputFormat = inputFormat; formats->outputFormat = outputFormat; } mCallback->onComponentConfigured(inputFormat, outputFormat); } void CCodec::initiateCreateInputSurface() { // TODO (new AMessage(kWhatCreateInputSurface, this))->post(); } void CCodec::createInputSurface() { sp<IGraphicBufferProducer> producer; sp<GraphicBufferSource> source(new GraphicBufferSource); status_t err = source->initCheck(); if (err != OK) { ALOGE("Failed to initialize graphic buffer source: %d", err); mCallback->onInputSurfaceCreationFailed(err); return; } producer = source->getIGraphicBufferProducer(); err = setupInputSurface(source); if (err != OK) { ALOGE("Failed to set up input surface: %d", err); mCallback->onInputSurfaceCreationFailed(err); return; } sp<AMessage> inputFormat; sp<AMessage> outputFormat; { Mutexed<Formats>::Locked formats(mFormats); inputFormat = formats->inputFormat; outputFormat = formats->outputFormat; } mCallback->onInputSurfaceCreated( inputFormat, outputFormat, new BufferProducerWrapper(producer)); } status_t CCodec::setupInputSurface(const sp<GraphicBufferSource> &source) { status_t err = mChannel->setGraphicBufferSource(source); if (err != OK) { return err; } // TODO: configure |source| with other settings. return OK; } void CCodec::initiateSetInputSurface(const sp<PersistentSurface> &surface) { sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this); msg->setObject("surface", surface); msg->post(); } void CCodec::setInputSurface(const sp<PersistentSurface> &surface) { // TODO (void)surface; mCallback->onInputSurfaceDeclined(ERROR_UNSUPPORTED); } void CCodec::initiateStart() { { Mutexed<State>::Locked state(mState); if (state->mState != ALLOCATED) { if (state->get() != ALLOCATED) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = STARTING; state->set(STARTING); } (new AMessage(kWhatStart, this))->post(); Loading @@ -307,13 +363,13 @@ void CCodec::start() { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState != STARTING) { if (state->get() != STARTING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } comp = state->mComp; comp = state->comp; } c2_status_t err = comp->start(); if (err != C2_OK) { Loading @@ -325,20 +381,20 @@ void CCodec::start() { sp<AMessage> outputFormat; { Mutexed<Formats>::Locked formats(mFormats); inputFormat = formats->mInputFormat; outputFormat = formats->mOutputFormat; inputFormat = formats->inputFormat; outputFormat = formats->outputFormat; } mChannel->start(inputFormat, outputFormat); { Mutexed<State>::Locked state(mState); if (state->mState != STARTING) { if (state->get() != STARTING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = RUNNING; state->set(RUNNING); } mCallback->onStartCompleted(); } Loading @@ -354,17 +410,17 @@ void CCodec::initiateShutdown(bool keepComponentAllocated) { void CCodec::initiateStop() { { Mutexed<State>::Locked state(mState); if (state->mState == ALLOCATED || state->mState == RELEASED || state->mState == STOPPING || state->mState == RELEASING) { if (state->get() == ALLOCATED || state->get() == RELEASED || state->get() == STOPPING || state->get() == RELEASING) { // We're already stopped, released, or doing it right now. state.unlock(); mCallback->onStopCompleted(); state.lock(); return; } state->mState = STOPPING; state->set(STOPPING); } (new AMessage(kWhatStop, this))->post(); Loading @@ -374,19 +430,19 @@ void CCodec::stop() { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState == RELEASING) { if (state->get() == RELEASING) { state.unlock(); // We're already stopped or release is in progress. mCallback->onStopCompleted(); state.lock(); return; } else if (state->mState != STOPPING) { } else if (state->get() != STOPPING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } comp = state->mComp; comp = state->comp; } mChannel->stop(); status_t err = comp->stop(); Loading @@ -397,8 +453,8 @@ void CCodec::stop() { { Mutexed<State>::Locked state(mState); if (state->mState == STOPPING) { state->mState = ALLOCATED; if (state->get() == STOPPING) { state->set(ALLOCATED); } } mCallback->onStopCompleted(); Loading @@ -407,7 +463,7 @@ void CCodec::stop() { void CCodec::initiateRelease(bool sendCallback /* = true */) { { Mutexed<State>::Locked state(mState); if (state->mState == RELEASED || state->mState == RELEASING) { if (state->get() == RELEASED || state->get() == RELEASING) { // We're already released or doing it right now. if (sendCallback) { state.unlock(); Loading @@ -416,8 +472,8 @@ void CCodec::initiateRelease(bool sendCallback /* = true */) { } return; } if (state->mState == ALLOCATING) { state->mState = RELEASING; if (state->get() == ALLOCATING) { state->set(RELEASING); // With the altered state allocate() would fail and clean up. if (sendCallback) { state.unlock(); Loading @@ -426,7 +482,7 @@ void CCodec::initiateRelease(bool sendCallback /* = true */) { } return; } state->mState = RELEASING; state->set(RELEASING); } std::thread([this, sendCallback] { release(sendCallback); }).detach(); Loading @@ -436,7 +492,7 @@ void CCodec::release(bool sendCallback) { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState == RELEASED) { if (state->get() == RELEASED) { if (sendCallback) { state.unlock(); mCallback->onReleaseCompleted(); Loading @@ -444,15 +500,15 @@ void CCodec::release(bool sendCallback) { } return; } comp = state->mComp; comp = state->comp; } mChannel->stop(); comp->release(); { Mutexed<State>::Locked state(mState); state->mState = RELEASED; state->mComp.reset(); state->set(RELEASED); state->comp.reset(); } if (sendCallback) { mCallback->onReleaseCompleted(); Loading @@ -466,11 +522,11 @@ status_t CCodec::setSurface(const sp<Surface> &surface) { void CCodec::signalFlush() { { Mutexed<State>::Locked state(mState); if (state->mState != RUNNING) { if (state->get() != RUNNING) { mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); return; } state->mState = FLUSHING; state->set(FLUSHING); } (new AMessage(kWhatFlush, this))->post(); Loading @@ -480,13 +536,13 @@ void CCodec::flush() { std::shared_ptr<C2Component> comp; { Mutexed<State>::Locked state(mState); if (state->mState != FLUSHING) { if (state->get() != FLUSHING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } comp = state->mComp; comp = state->comp; } mChannel->stop(); Loading @@ -502,7 +558,7 @@ void CCodec::flush() { { Mutexed<State>::Locked state(mState); state->mState = FLUSHED; state->set(FLUSHED); } mCallback->onFlushCompleted(); } Loading @@ -510,26 +566,26 @@ void CCodec::flush() { void CCodec::signalResume() { { Mutexed<State>::Locked state(mState); if (state->mState != FLUSHED) { if (state->get() != FLUSHED) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = RESUMING; state->set(RESUMING); } mChannel->start(nullptr, nullptr); { Mutexed<State>::Locked state(mState); if (state->mState != RESUMING) { if (state->get() != RESUMING) { state.unlock(); mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); state.lock(); return; } state->mState = RUNNING; state->set(RUNNING); } } Loading @@ -545,6 +601,14 @@ void CCodec::signalRequestIDRFrame() { // TODO } void CCodec::onWorkDone(std::vector<std::unique_ptr<C2Work>> &workItems) { Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); for (std::unique_ptr<C2Work> &item : workItems) { queue->push_back(std::move(item)); } (new AMessage(kWhatWorkDone, this))->post(); } void CCodec::onMessageReceived(const sp<AMessage> &msg) { TimePoint now = std::chrono::steady_clock::now(); switch (msg->what()) { Loading Loading @@ -582,6 +646,37 @@ void CCodec::onMessageReceived(const sp<AMessage> &msg) { flush(); break; } case kWhatCreateInputSurface: { // Surface operations may be briefly blocking. setDeadline(now + 100ms); createInputSurface(); break; } case kWhatSetInputSurface: { // Surface operations may be briefly blocking. setDeadline(now + 100ms); sp<RefBase> obj; CHECK(msg->findObject("surface", &obj)); sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get())); setInputSurface(surface); break; } case kWhatWorkDone: { std::unique_ptr<C2Work> work; { Mutexed<std::list<std::unique_ptr<C2Work>>>::Locked queue(mWorkDoneQueue); if (queue->empty()) { break; } work.swap(queue->front()); queue->pop_front(); if (!queue->empty()) { (new AMessage(kWhatWorkDone, this))->post(); } } mChannel->onWorkDone(work); break; } default: { ALOGE("unrecognized message"); break; Loading