codec2.cpp revision 52bffe176c343075c196c072aa7924de3abdd1b5
152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin// Copyright 2017 The Chromium Authors. All rights reserved.
252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin// Use of this source code is governed by a BSD-style license that can be
352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin// found in the LICENSE file.
452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin//#define LOG_NDEBUG 0
652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#define LOG_TAG "codec2"
752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <inttypes.h>
952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <fcntl.h>
1052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <stdlib.h>
1152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <string.h>
1252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <sys/time.h>
1352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <sys/types.h>
1452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <sys/stat.h>
1552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
1652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <thread>
1752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
1852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include "C2VDAComponent.h"
1952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2AllocatorCrosGralloc.h>
2152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2AllocatorMemDealer.h>
2252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2Buffer.h>
2352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2BufferPriv.h>
2452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2Component.h>
2552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2VDASupport.h>
2652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2Work.h>
2752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <binder/IServiceManager.h>
2952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <binder/ProcessState.h>
3052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/ICrypto.h>
3152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/IMediaHTTPService.h>
3252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/foundation/ABuffer.h>
3352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/foundation/ALooper.h>
3452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/foundation/AMessage.h>
3552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/foundation/AUtils.h>
3652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/DataSource.h>
3752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MediaDefs.h>
3852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MediaErrors.h>
3952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MediaExtractor.h>
4052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MediaSource.h>
4152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MetaData.h>
4252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/Utils.h>
4352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
4452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <gui/GLConsumer.h>
4552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <gui/IProducerListener.h>
4652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <gui/Surface.h>
4752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <gui/SurfaceComposerClient.h>
4852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
4952bffe176c343075c196c072aa7924de3abdd1b5Johny Linusing namespace android;
5052bffe176c343075c196c072aa7924de3abdd1b5Johny Linusing namespace std::chrono_literals;
5152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
5252bffe176c343075c196c072aa7924de3abdd1b5Johny Linnamespace {
5352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
5452bffe176c343075c196c072aa7924de3abdd1b5Johny Linconst int kWidth = 416;
5552bffe176c343075c196c072aa7924de3abdd1b5Johny Linconst int kHeight = 240;  // BigBuckBunny.mp4
5652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin//const int kWidth = 560;
5752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin//const int kHeight = 320;  // small.mp4
5852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
5952bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass C2VDALinearBuffer : public C2Buffer {
6052bffe176c343075c196c072aa7924de3abdd1b5Johny Linpublic:
6152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    explicit C2VDALinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
6252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        : C2Buffer({ block->share(block->offset(), block->size(), ::android::C2Fence()) }) {}
6352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin};
6452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
6552bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass Listener;
6652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
6752bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass SimplePlayer {
6852bffe176c343075c196c072aa7924de3abdd1b5Johny Linpublic:
6952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SimplePlayer();
7052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    ~SimplePlayer();
7152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
7252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    void onWorkDone(std::weak_ptr<C2Component> component,
7352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    std::vector<std::unique_ptr<C2Work>> workItems);
7452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    void onTripped(std::weak_ptr<C2Component> component,
7552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                   std::vector<std::shared_ptr<C2SettingResult>> settingResult);
7652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    void onError(std::weak_ptr<C2Component> component, uint32_t errorCode);
7752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
7852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    status_t play(const sp<IMediaSource> &source);
7952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
8052bffe176c343075c196c072aa7924de3abdd1b5Johny Linprivate:
8152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    typedef std::unique_lock<std::mutex> ULock;
8252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
8352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    enum {
8452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        kInputBufferCount = 8,
8552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        kDefaultInputBufferSize = 1024 * 1024,
8652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    };
8752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
8852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<Listener> mListener;
8952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
9052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<IProducerListener> mProducerListener;
9152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
9252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    // Allocators
9352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<C2Allocator> mLinearAlloc;
9452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<C2BlockPool> mLinearBlockPool;
9552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
9652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::mutex mQueueLock;
9752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::condition_variable mQueueCondition;
9852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::list<std::unique_ptr<C2Work>> mWorkQueue;
9952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
10052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::mutex mProcessedLock;
10152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::condition_variable mProcessedCondition;
10252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::list<std::unique_ptr<C2Work>> mProcessedWork;
10352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
10452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<Surface> mSurface;
10552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<SurfaceComposerClient> mComposerClient;
10652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<SurfaceControl> mControl;
10752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin};
10852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
10952bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass Listener : public C2Component::Listener {
11052bffe176c343075c196c072aa7924de3abdd1b5Johny Linpublic:
11152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    explicit Listener(SimplePlayer *thiz) : mThis(thiz) {}
11252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual ~Listener() = default;
11352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
11452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
11552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                               std::vector<std::unique_ptr<C2Work>> workItems) override {
11652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mThis->onWorkDone(component, std::move(workItems));
11752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
11852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
11952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual void onTripped_nb(
12052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            std::weak_ptr<C2Component> component,
12152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
12252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mThis->onTripped(component, settingResult);
12352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
12452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
12552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual void onError_nb(std::weak_ptr<C2Component> component,
12652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                            uint32_t errorCode) override {
12752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mThis->onError(component, errorCode);
12852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
12952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
13052bffe176c343075c196c072aa7924de3abdd1b5Johny Linprivate:
13152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SimplePlayer * const mThis;
13252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin};
13352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
13452bffe176c343075c196c072aa7924de3abdd1b5Johny LinSimplePlayer::SimplePlayer()
13552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    : mListener(new Listener(this)),
13652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin      mProducerListener(new DummyProducerListener),
13752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin      mComposerClient(new SurfaceComposerClient) {
13852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK_EQ(mComposerClient->initCheck(), OK);
13952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
14052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<C2AllocatorStore> store = getCodec2VDAAllocatorStore();
14152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAlloc), C2_OK);
14252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
14352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mLinearBlockPool = std::make_shared<C2BasicLinearBlockPool>(mLinearAlloc);
14452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
14552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mControl = mComposerClient->createSurface(String8("A Surface"),
14652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                                              kWidth, kHeight, HAL_PIXEL_FORMAT_YV12);
14752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
14852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK(mControl != nullptr);
14952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK(mControl->isValid());
15052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
15152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SurfaceComposerClient::openGlobalTransaction();
15252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK_EQ(mControl->setLayer(INT_MAX), OK);
15352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK_EQ(mControl->show(), OK);
15452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SurfaceComposerClient::closeGlobalTransaction();
15552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
15652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mSurface = mControl->getSurface();
15752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK(mSurface != nullptr);
15852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mSurface->connect(NATIVE_WINDOW_API_CPU, mProducerListener);
15952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
16052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
16152bffe176c343075c196c072aa7924de3abdd1b5Johny LinSimplePlayer::~SimplePlayer() {
16252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mComposerClient->dispose();
16352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
16452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
16552bffe176c343075c196c072aa7924de3abdd1b5Johny Linvoid SimplePlayer::onWorkDone(
16652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::weak_ptr<C2Component> component, std::vector<std::unique_ptr<C2Work>> workItems) {
16752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void) component;
16852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    ULock l(mProcessedLock);
16952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (auto & item : workItems) {
17052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mProcessedWork.emplace_back(std::move(item));
17152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
17252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mProcessedCondition.notify_all();
17352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
17452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
17552bffe176c343075c196c072aa7924de3abdd1b5Johny Linvoid SimplePlayer::onTripped(
17652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::weak_ptr<C2Component> component,
17752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::vector<std::shared_ptr<C2SettingResult>> settingResult) {
17852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void) component;
17952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void) settingResult;
18052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    // TODO
18152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
18252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
18352bffe176c343075c196c072aa7924de3abdd1b5Johny Linvoid SimplePlayer::onError(std::weak_ptr<C2Component> component, uint32_t errorCode) {
18452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void) component;
18552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void) errorCode;
18652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    // TODO
18752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
18852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
18952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin// TODO(johnylin): remove this when we move the development env to P
19052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin// from master: system/core/libcutils/native_handle.c
19152bffe176c343075c196c072aa7924de3abdd1b5Johny Linnative_handle_t* native_handle_clone(const native_handle_t* handle) {
19252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
19352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (clone == nullptr) return nullptr;
19452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (int i = 0; i < handle->numFds; i++) {
19552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        clone->data[i] = dup(handle->data[i]);
19652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        ALOGV("clone handle fd: %d", clone->data[i]);
19752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (clone->data[i] == -1) {
19852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            clone->numFds = i;
19952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            native_handle_close(clone);
20052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            native_handle_delete(clone);
20152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return nullptr;
20252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
20352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
20452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds],
20552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin           sizeof(int) * handle->numInts);
20652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return clone;
20752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
20852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
20952bffe176c343075c196c072aa7924de3abdd1b5Johny Linstatus_t SimplePlayer::play(const sp<IMediaSource> &source) {
21052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<AMessage> format;
21152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void) convertMetaDataToMessage(source->getFormat(), &format);
21252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
21352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::deque<sp<ABuffer>> csds(2);
21452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    format->findBuffer("csd-0", &csds[0]);
21552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    format->findBuffer("csd-1", &csds[1]);
21652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
21752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    status_t err = source->start();
21852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
21952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (err != OK) {
22052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        ALOGE("source returned error %d (0x%08x)", err, err);
22152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "source returned error %d (0x%08x)\n", err, err);
22252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return err;
22352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
22452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
22552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<C2Component> component(std::make_shared<C2VDAComponent>("avc", 0));
22652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    component->setListener_sm(mListener);
22752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
22852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        C2PortBlockPoolsTuning::output::alloc_unique(
22952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                { static_cast<uint64_t>(C2BlockPool::BASIC_GRAPHIC) });
23052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::vector<std::unique_ptr<C2SettingResult>> result;
23152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    (void)component->intf()->config_nb({pools.get()}, &result);
23252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    component->start();
23352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
23452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mProcessedWork.clear();
23552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (int i = 0; i < kInputBufferCount; ++i) {
23652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mWorkQueue.emplace_back(new C2Work);
23752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
23852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
23952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::atomic_bool running(true);
24052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::thread surfaceThread([this, &running]() {
24152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        const sp<IGraphicBufferProducer> &igbp = mSurface->getIGraphicBufferProducer();
24252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::vector<std::shared_ptr<C2Buffer>> pendingDisplayBuffers;
24352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        pendingDisplayBuffers.resize(BufferQueue::NUM_BUFFER_SLOTS);
24452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        while (running) {
24552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            std::unique_ptr<C2Work> work;
24652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            {
24752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                ULock l(mProcessedLock);
24852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                if (mProcessedWork.empty()) {
24952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    mProcessedCondition.wait_for(l, 100ms);
25052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    if (mProcessedWork.empty()) {
25152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        continue;
25252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    }
25352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                }
25452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                work = std::move(mProcessedWork.front());
25552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                mProcessedWork.pop_front();
25652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
25752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
25852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (work->worklets_processed > 0) {
25952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                int slot;
26052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                sp<Fence> fence;
26152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                std::shared_ptr<C2Buffer> output = work->worklets.front()->output.buffers[0];
26252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                C2ConstGraphicBlock graphic_block = output->data().graphicBlocks().front();
26352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
26452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                // Create GraphicBuffer from cloning native_handle
26552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                native_handle_t* cloneHandle = native_handle_clone(graphic_block.handle());
26652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                sp<GraphicBuffer> buffer = new GraphicBuffer(
26752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        graphic_block.width(),
26852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        graphic_block.height(),
26952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        HAL_PIXEL_FORMAT_YCbCr_420_888,
27052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        GRALLOC_USAGE_SW_READ_OFTEN,
27152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        graphic_block.width(),
27252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        cloneHandle,
27352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        false);
27452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
27552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                CHECK_EQ(igbp->attachBuffer(&slot, buffer), OK);
27652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                ALOGV("attachBuffer slot=%d ts=%lld", slot,
27752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                      work->worklets.front()->output.ordinal.timestamp * 1000ll);
27852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
27952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                IGraphicBufferProducer::QueueBufferInput qbi(
28052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        work->worklets.front()->output.ordinal.timestamp * 1000ll,
28152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        false,
28252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        HAL_DATASPACE_UNKNOWN,
28352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        Rect(graphic_block.width(), graphic_block.height()),
28452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
28552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        0,
28652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        Fence::NO_FENCE,
28752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        0);
28852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                IGraphicBufferProducer::QueueBufferOutput qbo;
28952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                CHECK_EQ(igbp->queueBuffer(slot, qbi, &qbo), OK);
29052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
29152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                // If the slot is reused then we can make sure the previous graphic buffer is
29252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                // displayed (consumed), so we could returned the graphic buffer.
29352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                pendingDisplayBuffers[slot].swap(output);
29452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
29552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                // Remember to close the cloned handle.
29652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                native_handle_close(cloneHandle);
29752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                native_handle_delete(cloneHandle);
29852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
29952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
30052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            // input buffers should be cleared in component side.
30152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            CHECK(work->input.buffers.empty());
30252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            work->worklets.clear();
30352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            work->worklets_processed = 0;
30452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
30552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
30652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                running.store(false);  // stop the thread
30752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
30852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
30952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            ULock l(mQueueLock);
31052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            mWorkQueue.emplace_back(std::move(work));
31152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            mQueueCondition.notify_all();
31252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
31352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    });
31452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
31552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    long numFrames = 0;
31652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
31752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (;;) {
31852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        size_t size = 0u;
31952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        void *data = nullptr;
32052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        int64_t timestamp = 0u;
32152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        MediaBuffer* buffer = nullptr;
32252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        sp<ABuffer> csd;
32352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (!csds.empty()) {
32452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            csd = std::move(csds.front());
32552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            csds.pop_front();
32652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            size = csd->size();
32752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            data = csd->data();
32852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        } else {
32952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            status_t err = source->read(&buffer);
33052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (err != OK) {
33152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                CHECK(buffer == nullptr);
33252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
33352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                if (err == INFO_FORMAT_CHANGED) {
33452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    continue;
33552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                }
33652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
33752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                break;
33852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
33952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            sp<MetaData> meta = buffer->meta_data();
34052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            CHECK(meta->findInt64(kKeyTime, &timestamp));
34152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
34252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            size = buffer->size();
34352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            data = buffer->data();
34452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
34552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
34652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // Prepare C2Work
34752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
34852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::unique_ptr<C2Work> work;
34952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        while (!work) {
35052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            ULock l(mQueueLock);
35152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (!mWorkQueue.empty()) {
35252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                work = std::move(mWorkQueue.front());
35352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                mWorkQueue.pop_front();
35452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            } else {
35552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                mQueueCondition.wait_for(l, 100ms);
35652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
35752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
35852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.flags = static_cast<C2BufferPack::flags_t>(0);
35952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.ordinal.timestamp = timestamp;
36052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.ordinal.frame_index = numFrames;
36152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
36252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // Allocate input buffer.
36352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::shared_ptr<C2LinearBlock> block;
36452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mLinearBlockPool->fetchLinearBlock(
36552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                size, { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite }, &block);
36652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        C2WriteView view = block->map().get();
36752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (view.error() != C2_OK) {
36852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            fprintf(stderr, "C2LinearBlock::map() failed : %d\n", view.error());
36952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            break;
37052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
37152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        memcpy(view.base(), data, size);
37252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
37352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.buffers.clear();
37452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.buffers.emplace_back(new C2VDALinearBuffer(std::move(block)));
37552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->worklets.clear();
37652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->worklets.emplace_back(new C2Worklet);
37752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
37852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::list<std::unique_ptr<C2Work>> items;
37952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        items.push_back(std::move(work));
38052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
38152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // DO THE DECODING
38252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        component->queue_nb(&items);
38352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
38452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (buffer) {
38552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            buffer->release();
38652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
38752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        ++numFrames;
38852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
38952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    component->drain_nb(C2Component::DRAIN_COMPONENT);
39052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
39152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    surfaceThread.join();
39252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
39352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    source->stop();
39452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    component->stop();
39552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    printf("finished...\n");
39652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return OK;
39752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
39852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
39952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}  // namespace
40052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
40152bffe176c343075c196c072aa7924de3abdd1b5Johny Linstatic bool getMediaSourceFromFile(const char* filename, sp<IMediaSource>* source) {
40252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    source->clear();
40352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
40452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<DataSource> dataSource =
40552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            DataSource::CreateFromURI(nullptr /* httpService */, filename);
40652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
40752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (dataSource == nullptr) {
40852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "Unable to create data source.\n");
40952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return false;
41052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
41152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
41252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
41352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (extractor == nullptr) {
41452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "could not create extractor.\n");
41552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return false;
41652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
41752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
41852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (size_t i = 0, numTracks = extractor->countTracks(); i < numTracks; ++i) {
41952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        sp<MetaData> meta =
42052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                extractor->getTrackMetaData(i, MediaExtractor::kIncludeExtensiveMetaData);
42152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (meta == nullptr) {
42252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            continue;
42352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
42452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        const char *mime;
42552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        meta->findCString(kKeyMIMEType, &mime);
42652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // TODO: only h264 is working now, adapt other codec (vp8/9) stream in the future.
42752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (!strncasecmp(mime, "video/avc", 9)) {
42852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            *source = extractor->getTrack(i);
42952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (*source == nullptr) {
43052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                fprintf(stderr, "It's nullptr track for track %zu.\n", i);
43152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                return false;
43252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
43352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return true;
43452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
43552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
43652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    fprintf(stderr, "No AVC track found.\n");
43752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return false;
43852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
43952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
44052bffe176c343075c196c072aa7924de3abdd1b5Johny Linstatic void usage(const char *me) {
44152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    fprintf(stderr, "usage: %s [options] [input_filename]...\n", me);
44252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    fprintf(stderr, "       -h(elp)\n");
44352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
44452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
44552bffe176c343075c196c072aa7924de3abdd1b5Johny Linint main(int argc, char **argv) {
44652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    android::ProcessState::self()->startThreadPool();
44752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
44852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    int res;
44952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    while ((res = getopt(argc, argv, "h")) >= 0) {
45052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        switch (res) {
45152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            case 'h':
45252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            default:
45352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            {
45452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                usage(argv[0]);
45552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                exit(1);
45652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                break;
45752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
45852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
45952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
46052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
46152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    argc -= optind;
46252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    argv += optind;
46352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
46452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (argc < 1) {
46552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "No input file specified\n");
46652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return 1;
46752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
46852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
46952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SimplePlayer player;
47052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
47152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (int k = 0; k < argc; ++k) {
47252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        sp<IMediaSource> mediaSource;
47352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (!getMediaSourceFromFile(argv[k], &mediaSource)) {
47452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            fprintf(stderr, "Unable to get media source from file: %s\n", argv[k]);
47552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return -1;
47652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
47752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (player.play(mediaSource) != OK) {
47852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            fprintf(stderr, "Player failed to play media source: %s\n", argv[k]);
47952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return -1;
48052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
48152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
48252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
48352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return 0;
48452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
485