diff options
Diffstat (limited to 'media/codecs/cmds/codec2.cpp')
| -rw-r--r-- | media/codecs/cmds/codec2.cpp | 482 |
1 files changed, 0 insertions, 482 deletions
diff --git a/media/codecs/cmds/codec2.cpp b/media/codecs/cmds/codec2.cpp deleted file mode 100644 index 2cbbcd8..0000000 --- a/media/codecs/cmds/codec2.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <thread> - -//#define LOG_NDEBUG 0 -#define LOG_TAG "codec2" -#include <log/log.h> - -#include <binder/IServiceManager.h> -#include <binder/ProcessState.h> -#include <datasource/DataSourceFactory.h> -#include <media/DataSource.h> -#include <media/IMediaHTTPService.h> -#include <media/stagefright/MediaSource.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ALooper.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/foundation/AUtils.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MediaExtractorFactory.h> -#include <media/stagefright/MetaData.h> -#include <media/stagefright/Utils.h> - -#include <gui/GLConsumer.h> -#include <gui/IProducerListener.h> -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> - -#include <C2AllocatorGralloc.h> -#include <C2Buffer.h> -#include <C2BufferPriv.h> -#include <C2Component.h> -#include <C2Config.h> -#include <C2Debug.h> -#include <C2PlatformSupport.h> -#include <C2Work.h> - -using namespace android; -using namespace std::chrono_literals; - -namespace { - -class LinearBuffer : public C2Buffer { -public: - explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block) - : C2Buffer({ block->share(block->offset(), block->size(), ::C2Fence()) }) {} -}; - -class Listener; - -class SimplePlayer { -public: - SimplePlayer(); - ~SimplePlayer(); - - void onWorkDone(std::weak_ptr<C2Component> component, - std::list<std::unique_ptr<C2Work>> workItems); - void onTripped(std::weak_ptr<C2Component> component, - std::vector<std::shared_ptr<C2SettingResult>> settingResult); - void onError(std::weak_ptr<C2Component> component, uint32_t errorCode); - - void play(const sp<IMediaSource> &source); - -private: - typedef std::unique_lock<std::mutex> ULock; - - std::shared_ptr<Listener> mListener; - std::shared_ptr<C2Component> mComponent; - - sp<IProducerListener> mProducerListener; - - std::atomic_int mLinearPoolId; - - std::shared_ptr<C2Allocator> mAllocIon; - std::shared_ptr<C2BlockPool> mLinearPool; - - std::mutex mQueueLock; - std::condition_variable mQueueCondition; - std::list<std::unique_ptr<C2Work>> mWorkQueue; - - std::mutex mProcessedLock; - std::condition_variable mProcessedCondition; - std::list<std::unique_ptr<C2Work>> mProcessedWork; - - sp<Surface> mSurface; - sp<SurfaceComposerClient> mComposerClient; - sp<SurfaceControl> mControl; -}; - -class Listener : public C2Component::Listener { -public: - explicit Listener(SimplePlayer *thiz) : mThis(thiz) {} - virtual ~Listener() = default; - - virtual void onWorkDone_nb(std::weak_ptr<C2Component> component, - std::list<std::unique_ptr<C2Work>> workItems) override { - mThis->onWorkDone(component, std::move(workItems)); - } - - virtual void onTripped_nb(std::weak_ptr<C2Component> component, - std::vector<std::shared_ptr<C2SettingResult>> settingResult) override { - mThis->onTripped(component, settingResult); - } - - virtual void onError_nb(std::weak_ptr<C2Component> component, - uint32_t errorCode) override { - mThis->onError(component, errorCode); - } - -private: - SimplePlayer * const mThis; -}; - - -SimplePlayer::SimplePlayer() - : mListener(new Listener(this)), - mProducerListener(new DummyProducerListener), - mLinearPoolId(C2BlockPool::PLATFORM_START), - mComposerClient(new SurfaceComposerClient) { - CHECK_EQ(mComposerClient->initCheck(), (status_t)OK); - - std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore(); - CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK); - mLinearPool = std::make_shared<C2PooledBlockPool>(mAllocIon, mLinearPoolId++); - - mControl = mComposerClient->createSurface( - String8("A Surface"), - 1280, - 800, - HAL_PIXEL_FORMAT_YV12); - //PIXEL_FORMAT_RGB_565); - - CHECK(mControl != nullptr); - CHECK(mControl->isValid()); - - SurfaceComposerClient::Transaction{} - .setLayer(mControl, INT_MAX) - .show(mControl) - .apply(); - - mSurface = mControl->getSurface(); - CHECK(mSurface != nullptr); - mSurface->connect(NATIVE_WINDOW_API_CPU, mProducerListener); -} - -SimplePlayer::~SimplePlayer() { - mComposerClient->dispose(); -} - -void SimplePlayer::onWorkDone( - std::weak_ptr<C2Component> component, std::list<std::unique_ptr<C2Work>> workItems) { - ALOGV("SimplePlayer::onWorkDone"); - (void) component; - ULock l(mProcessedLock); - for (auto & item : workItems) { - mProcessedWork.push_back(std::move(item)); - } - mProcessedCondition.notify_all(); -} - -void SimplePlayer::onTripped( - std::weak_ptr<C2Component> component, - std::vector<std::shared_ptr<C2SettingResult>> settingResult) { - (void) component; - (void) settingResult; - // TODO -} - -void SimplePlayer::onError(std::weak_ptr<C2Component> component, uint32_t errorCode) { - (void) component; - (void) errorCode; - // TODO -} - -void SimplePlayer::play(const sp<IMediaSource> &source) { - ALOGV("SimplePlayer::play"); - sp<AMessage> format; - (void) convertMetaDataToMessage(source->getFormat(), &format); - - sp<ABuffer> csd0, csd1; - format->findBuffer("csd-0", &csd0); - format->findBuffer("csd-1", &csd1); - - status_t err = source->start(); - - if (err != OK) { - fprintf(stderr, "source returned error %d (0x%08x)\n", err, err); - return; - } - - std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore(); - std::shared_ptr<C2Component> component; - (void)store->createComponent("c2.android.avc.decoder", &component); - - (void)component->setListener_vb(mListener, C2_DONT_BLOCK); - std::unique_ptr<C2PortBlockPoolsTuning::output> pools = - C2PortBlockPoolsTuning::output::AllocUnique({ (uint64_t)C2BlockPool::BASIC_GRAPHIC }); - std::vector<std::unique_ptr<C2SettingResult>> result; - (void)component->intf()->config_vb({pools.get()}, C2_DONT_BLOCK, &result); - component->start(); - - for (int i = 0; i < 8; ++i) { - mWorkQueue.emplace_back(new C2Work); - } - - std::atomic_bool running(true); - std::thread surfaceThread([this, &running]() { - const sp<IGraphicBufferProducer> &igbp = mSurface->getIGraphicBufferProducer(); - while (running) { - std::unique_ptr<C2Work> work; - { - ULock l(mProcessedLock); - if (mProcessedWork.empty()) { - mProcessedCondition.wait_for(l, 100ms); - if (mProcessedWork.empty()) { - continue; - } - } - work.swap(mProcessedWork.front()); - mProcessedWork.pop_front(); - } - int slot; - sp<Fence> fence; - ALOGV("Render: Frame #%lld", work->worklets.front()->output.ordinal.frameIndex.peekll()); - const std::shared_ptr<C2Buffer> &output = work->worklets.front()->output.buffers[0]; - if (output) { - const C2ConstGraphicBlock block = output->data().graphicBlocks().front(); - native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(block.handle()); - sp<GraphicBuffer> buffer(new GraphicBuffer( - grallocHandle, - GraphicBuffer::CLONE_HANDLE, - block.width(), - block.height(), - HAL_PIXEL_FORMAT_YV12, - 1, - (uint64_t)GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - block.width())); - native_handle_delete(grallocHandle); - - status_t err = igbp->attachBuffer(&slot, buffer); - - IGraphicBufferProducer::QueueBufferInput qbi( - (work->worklets.front()->output.ordinal.timestamp * 1000ll).peekll(), - false, - HAL_DATASPACE_UNKNOWN, - Rect(block.width(), block.height()), - NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, - 0, - Fence::NO_FENCE, - 0); - IGraphicBufferProducer::QueueBufferOutput qbo; - err = igbp->queueBuffer(slot, qbi, &qbo); - } - - work->input.buffers.clear(); - work->worklets.clear(); - - ULock l(mQueueLock); - mWorkQueue.push_back(std::move(work)); - mQueueCondition.notify_all(); - } - ALOGV("render loop finished"); - }); - - long numFrames = 0; - mLinearPool.reset(new C2PooledBlockPool(mAllocIon, mLinearPoolId++)); - - for (;;) { - size_t size = 0u; - void *data = nullptr; - int64_t timestamp = 0u; - MediaBufferBase *buffer = nullptr; - sp<ABuffer> csd; - if (csd0 != nullptr) { - csd = csd0; - csd0 = nullptr; - } else if (csd1 != nullptr) { - csd = csd1; - csd1 = nullptr; - } else { - status_t err = source->read(&buffer); - if (err != OK) { - CHECK(buffer == nullptr); - - if (err == INFO_FORMAT_CHANGED) { - continue; - } - - break; - } - MetaDataBase &meta = buffer->meta_data(); - CHECK(meta.findInt64(kKeyTime, ×tamp)); - - size = buffer->size(); - data = buffer->data(); - } - - if (csd != nullptr) { - size = csd->size(); - data = csd->data(); - } - - // Prepare C2Work - - std::unique_ptr<C2Work> work; - while (!work) { - ULock l(mQueueLock); - if (!mWorkQueue.empty()) { - work.swap(mWorkQueue.front()); - mWorkQueue.pop_front(); - } else { - mQueueCondition.wait_for(l, 100ms); - } - } - work->input.flags = (C2FrameData::flags_t)0; - work->input.ordinal.timestamp = timestamp; - work->input.ordinal.frameIndex = numFrames; - - std::shared_ptr<C2LinearBlock> block; - mLinearPool->fetchLinearBlock( - size, - { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE }, - &block); - C2WriteView view = block->map().get(); - if (view.error() != C2_OK) { - fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error()); - break; - } - memcpy(view.base(), data, size); - - work->input.buffers.clear(); - work->input.buffers.emplace_back(new LinearBuffer(block)); - work->worklets.clear(); - work->worklets.emplace_back(new C2Worklet); - - std::list<std::unique_ptr<C2Work>> items; - items.push_back(std::move(work)); - - ALOGV("Frame #%ld size = %zu", numFrames, size); - // DO THE DECODING - component->queue_nb(&items); - - if (buffer) { - buffer->release(); - buffer = nullptr; - } - - ++numFrames; - } - ALOGV("main loop finished"); - source->stop(); - running.store(false); - surfaceThread.join(); - - component->release(); - printf("\n"); -} - -} // namespace - -static void usage(const char *me) { - fprintf(stderr, "usage: %s [options] [input_filename]\n", me); - fprintf(stderr, " -h(elp)\n"); -} - -int main(int argc, char **argv) { - android::ProcessState::self()->startThreadPool(); - - int res; - while ((res = getopt(argc, argv, "h")) >= 0) { - switch (res) { - case 'h': - default: - { - usage(argv[0]); - exit(1); - break; - } - } - } - - argc -= optind; - argv += optind; - - if (argc < 1) { - fprintf(stderr, "No input file specified\n"); - return 1; - } - - status_t err = OK; - SimplePlayer player; - - for (int k = 0; k < argc && err == OK; ++k) { - const char *filename = argv[k]; - - sp<DataSource> dataSource = - DataSourceFactory::getInstance()->CreateFromURI(nullptr /* httpService */, filename); - - if (strncasecmp(filename, "sine:", 5) && dataSource == nullptr) { - fprintf(stderr, "Unable to create data source.\n"); - return 1; - } - - Vector<sp<IMediaSource> > mediaSources; - sp<IMediaSource> mediaSource; - - sp<IMediaExtractor> extractor = MediaExtractorFactory::Create(dataSource); - - if (extractor == nullptr) { - fprintf(stderr, "could not create extractor.\n"); - return -1; - } - - sp<MetaData> meta = extractor->getMetaData(); - - if (meta != nullptr) { - const char *mime; - if (!meta->findCString(kKeyMIMEType, &mime)) { - fprintf(stderr, "extractor did not provide MIME type.\n"); - return -1; - } - } - - size_t numTracks = extractor->countTracks(); - - size_t i; - for (i = 0; i < numTracks; ++i) { - meta = extractor->getTrackMetaData(i, 0); - - if (meta == nullptr) { - break; - } - const char *mime; - meta->findCString(kKeyMIMEType, &mime); - - // TODO: allowing AVC only for the time being - if (!strncasecmp(mime, "video/avc", 9)) { - break; - } - - meta = nullptr; - } - - if (meta == nullptr) { - fprintf(stderr, "No AVC track found.\n"); - return -1; - } - - mediaSource = extractor->getTrack(i); - if (mediaSource == nullptr) { - fprintf(stderr, "skip NULL track %zu, total tracks %zu.\n", i, numTracks); - return -1; - } - - player.play(mediaSource); - } - - return 0; -} |
