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
8c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <C2VDAComponent.h>
98a2118e656587a22ebf4c1a4c23874fea45062b4Johny Lin
1052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2Buffer.h>
1152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2BufferPriv.h>
1252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2Component.h>
1385e1ec6ac0790a8f527ffc310a9f1a9be6589241Pin-chih Lin#include <C2PlatformSupport.h>
1452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <C2Work.h>
1547d00e960809f081a3410d4937ffb2725571bf62Lev Rumyantsev#include <SimpleC2Interface.h>
1652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
1752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <binder/IServiceManager.h>
1852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <binder/ProcessState.h>
19c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <gui/GLConsumer.h>
20c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <gui/IProducerListener.h>
21c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <gui/Surface.h>
22c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <gui/SurfaceComposerClient.h>
231ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin#include <media/DataSource.h>
2452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/ICrypto.h>
2552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/IMediaHTTPService.h>
261ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin#include <media/MediaExtractor.h>
271ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin#include <media/MediaSource.h>
281ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin#include <media/stagefright/DataSourceFactory.h>
2952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MediaDefs.h>
3052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MediaErrors.h>
311ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin#include <media/stagefright/MediaExtractorFactory.h>
3252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/MetaData.h>
3352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin#include <media/stagefright/Utils.h>
34a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin#include <media/stagefright/foundation/ABuffer.h>
35a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin#include <media/stagefright/foundation/ALooper.h>
36a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin#include <media/stagefright/foundation/AMessage.h>
37a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin#include <media/stagefright/foundation/AUtils.h>
3852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
39c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <fcntl.h>
40c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <inttypes.h>
41c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <stdlib.h>
42c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <string.h>
43c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <sys/stat.h>
44c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <sys/time.h>
45c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <sys/types.h>
46c6d0b6f730a74e2d10a414ba5b368fb7cd87f78dJohny Lin#include <thread>
4752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
4852bffe176c343075c196c072aa7924de3abdd1b5Johny Linusing namespace android;
4952bffe176c343075c196c072aa7924de3abdd1b5Johny Linusing namespace std::chrono_literals;
5052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
5152bffe176c343075c196c072aa7924de3abdd1b5Johny Linnamespace {
5252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
53226ec4605d573878f8062524e271daf2732a650aPin-chih Linconst std::string kH264DecoderName = "c2.vda.avc.decoder";
54226ec4605d573878f8062524e271daf2732a650aPin-chih Linconst std::string kVP8DecoderName = "c2.vda.vp8.decoder";
55226ec4605d573878f8062524e271daf2732a650aPin-chih Linconst std::string kVP9DecoderName = "c2.vda.vp9.decoder";
569be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin
5752bffe176c343075c196c072aa7924de3abdd1b5Johny Linconst int kWidth = 416;
5852bffe176c343075c196c072aa7924de3abdd1b5Johny Linconst int kHeight = 240;  // BigBuckBunny.mp4
5952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin//const int kWidth = 560;
6052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin//const int kHeight = 320;  // small.mp4
619be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Linconst std::string kComponentName = kH264DecoderName;
6252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
6352bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass C2VDALinearBuffer : public C2Buffer {
6452bffe176c343075c196c072aa7924de3abdd1b5Johny Linpublic:
6552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    explicit C2VDALinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
6693e4f225df19e43300fb3b29e6f95b4e63daa4c7Lajos Molnar          : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
6752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin};
6852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
6952bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass Listener;
7052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
7152bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass SimplePlayer {
7252bffe176c343075c196c072aa7924de3abdd1b5Johny Linpublic:
7352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SimplePlayer();
7452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    ~SimplePlayer();
7552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
7652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    void onWorkDone(std::weak_ptr<C2Component> component,
77fa7abe5b3914c3041874b360f511b132e6bf1116Lajos Molnar                    std::list<std::unique_ptr<C2Work>> workItems);
7852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    void onTripped(std::weak_ptr<C2Component> component,
7952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                   std::vector<std::shared_ptr<C2SettingResult>> settingResult);
8052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    void onError(std::weak_ptr<C2Component> component, uint32_t errorCode);
8152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
82a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    status_t play(const sp<IMediaSource>& source);
8352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
8452bffe176c343075c196c072aa7924de3abdd1b5Johny Linprivate:
8552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    typedef std::unique_lock<std::mutex> ULock;
8652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
8752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    enum {
8852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        kInputBufferCount = 8,
8952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        kDefaultInputBufferSize = 1024 * 1024,
9052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    };
9152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
9252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<Listener> mListener;
9352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
9452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<IProducerListener> mProducerListener;
9552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
9652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    // Allocators
9752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<C2Allocator> mLinearAlloc;
9852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::shared_ptr<C2BlockPool> mLinearBlockPool;
9952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
10052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::mutex mQueueLock;
10152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::condition_variable mQueueCondition;
10252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::list<std::unique_ptr<C2Work>> mWorkQueue;
10352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
10452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::mutex mProcessedLock;
10552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::condition_variable mProcessedCondition;
10652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::list<std::unique_ptr<C2Work>> mProcessedWork;
10752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
10852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<Surface> mSurface;
10952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<SurfaceComposerClient> mComposerClient;
11052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    sp<SurfaceControl> mControl;
11152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin};
11252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
11352bffe176c343075c196c072aa7924de3abdd1b5Johny Linclass Listener : public C2Component::Listener {
11452bffe176c343075c196c072aa7924de3abdd1b5Johny Linpublic:
115a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    explicit Listener(SimplePlayer* thiz) : mThis(thiz) {}
11652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual ~Listener() = default;
11752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
11852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
119fa7abe5b3914c3041874b360f511b132e6bf1116Lajos Molnar                               std::list<std::unique_ptr<C2Work>> workItems) override {
12052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mThis->onWorkDone(component, std::move(workItems));
12152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
12252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
12352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    virtual void onTripped_nb(
12452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            std::weak_ptr<C2Component> component,
12552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            std::vector<std::shared_ptr<C2SettingResult>> settingResult) override {
12652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mThis->onTripped(component, settingResult);
12752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
12852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
129a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    virtual void onError_nb(std::weak_ptr<C2Component> component, uint32_t errorCode) override {
13052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mThis->onError(component, errorCode);
13152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
13252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
13352bffe176c343075c196c072aa7924de3abdd1b5Johny Linprivate:
134a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    SimplePlayer* const mThis;
13552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin};
13652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
13752bffe176c343075c196c072aa7924de3abdd1b5Johny LinSimplePlayer::SimplePlayer()
138a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin      : mListener(new Listener(this)),
139a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        mProducerListener(new DummyProducerListener),
140a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        mComposerClient(new SurfaceComposerClient) {
14152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK_EQ(mComposerClient->initCheck(), OK);
14252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
1438a2118e656587a22ebf4c1a4c23874fea45062b4Johny Lin    std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
14452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAlloc), C2_OK);
14552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
14652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mLinearBlockPool = std::make_shared<C2BasicLinearBlockPool>(mLinearAlloc);
14752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
148a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    mControl = mComposerClient->createSurface(String8("A Surface"), kWidth, kHeight,
149a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin                                              HAL_PIXEL_FORMAT_YV12);
15052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
15152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK(mControl != nullptr);
15252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    CHECK(mControl->isValid());
15352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
1540deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin    SurfaceComposerClient::Transaction{}.setLayer(mControl, INT_MAX).show(mControl).apply();
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
165a891f0ea984eb1175467ebe1c0ec086977464a07Johny Linvoid SimplePlayer::onWorkDone(std::weak_ptr<C2Component> component,
166fa7abe5b3914c3041874b360f511b132e6bf1116Lajos Molnar                              std::list<std::unique_ptr<C2Work>> workItems) {
167a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    (void)component;
16852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    ULock l(mProcessedLock);
169a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    for (auto& item : workItems) {
17052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mProcessedWork.emplace_back(std::move(item));
17152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
17252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mProcessedCondition.notify_all();
17352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
17452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
175a891f0ea984eb1175467ebe1c0ec086977464a07Johny Linvoid SimplePlayer::onTripped(std::weak_ptr<C2Component> component,
176a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin                             std::vector<std::shared_ptr<C2SettingResult>> settingResult) {
177a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    (void)component;
178a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    (void)settingResult;
17952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    // TODO
18052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
18152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
18252bffe176c343075c196c072aa7924de3abdd1b5Johny Linvoid SimplePlayer::onError(std::weak_ptr<C2Component> component, uint32_t errorCode) {
183a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    (void)component;
184a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    (void)errorCode;
18552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    // TODO
18652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
18752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
188a891f0ea984eb1175467ebe1c0ec086977464a07Johny Linstatus_t SimplePlayer::play(const sp<IMediaSource>& source) {
1899be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    std::deque<sp<ABuffer>> csds;
1909be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    if (kComponentName == kH264DecoderName) {
1919be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        sp<AMessage> format;
192a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        (void)convertMetaDataToMessage(source->getFormat(), &format);
1939be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin
1949be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        csds.resize(2);
1959be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        format->findBuffer("csd-0", &csds[0]);
1969be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        format->findBuffer("csd-1", &csds[1]);
1979be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    }
19852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
19952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    status_t err = source->start();
20052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
20152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (err != OK) {
20252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        ALOGE("source returned error %d (0x%08x)", err, err);
20352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "source returned error %d (0x%08x)\n", err, err);
20452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return err;
20552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
20652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2071ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin    std::shared_ptr<C2Component> component(std::make_shared<C2VDAComponent>(
2081ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin            kComponentName, 0, std::make_shared<C2ReflectorHelper>()));
2091ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin
210a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    component->setListener_vb(mListener, C2_DONT_BLOCK);
21152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
21293e4f225df19e43300fb3b29e6f95b4e63daa4c7Lajos Molnar            C2PortBlockPoolsTuning::output::AllocUnique(
213a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin                    {static_cast<uint64_t>(C2BlockPool::BASIC_GRAPHIC)});
21452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::vector<std::unique_ptr<C2SettingResult>> result;
2152737fb61ca7ecd786b160ec5d79e3eaa48135606Lajos Molnar    (void)component->intf()->config_vb({pools.get()}, C2_DONT_BLOCK, &result);
21652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    component->start();
21752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
21852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    mProcessedWork.clear();
21952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (int i = 0; i < kInputBufferCount; ++i) {
22052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mWorkQueue.emplace_back(new C2Work);
22152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
22252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
22352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::atomic_bool running(true);
22452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    std::thread surfaceThread([this, &running]() {
225a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        const sp<IGraphicBufferProducer>& igbp = mSurface->getIGraphicBufferProducer();
22652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::vector<std::shared_ptr<C2Buffer>> pendingDisplayBuffers;
22752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        pendingDisplayBuffers.resize(BufferQueue::NUM_BUFFER_SLOTS);
22852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        while (running) {
22952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            std::unique_ptr<C2Work> work;
23052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            {
23152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                ULock l(mProcessedLock);
23252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                if (mProcessedWork.empty()) {
23352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    mProcessedCondition.wait_for(l, 100ms);
23452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    if (mProcessedWork.empty()) {
23552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                        continue;
23652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    }
23752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                }
23852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                work = std::move(mProcessedWork.front());
23952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                mProcessedWork.pop_front();
24052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
24152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2423760d5fdd7e60b68ed599d7322e2599efe7a13c9Johny Lin            CHECK_EQ(work->worklets.size(), 1u);
2433760d5fdd7e60b68ed599d7322e2599efe7a13c9Johny Lin            if (work->worklets.front()->output.buffers.size() == 1u) {
24452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                int slot;
24552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                sp<Fence> fence;
24652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                std::shared_ptr<C2Buffer> output = work->worklets.front()->output.buffers[0];
24752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                C2ConstGraphicBlock graphic_block = output->data().graphicBlocks().front();
24852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2490deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin                sp<GraphicBuffer> buffer(new GraphicBuffer(
2500deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin                        graphic_block.handle(), GraphicBuffer::CLONE_HANDLE, graphic_block.width(),
2510deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin                        graphic_block.height(), HAL_PIXEL_FORMAT_YCbCr_420_888, 1 /* layerCount */,
2520deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin                        GRALLOC_USAGE_SW_READ_OFTEN, graphic_block.width()));
25352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
25452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                CHECK_EQ(igbp->attachBuffer(&slot, buffer), OK);
25552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                ALOGV("attachBuffer slot=%d ts=%lld", slot,
2562a2b90179d72e158c74982599752c92aac9029deLajos Molnar                      (work->worklets.front()->output.ordinal.timestamp * 1000ll).peekll());
25752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
25852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                IGraphicBufferProducer::QueueBufferInput qbi(
2592a2b90179d72e158c74982599752c92aac9029deLajos Molnar                        (work->worklets.front()->output.ordinal.timestamp * 1000ll).peekll(), false,
260a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin                        HAL_DATASPACE_UNKNOWN, Rect(graphic_block.width(), graphic_block.height()),
261a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin                        NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, 0, Fence::NO_FENCE, 0);
26252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                IGraphicBufferProducer::QueueBufferOutput qbo;
26352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                CHECK_EQ(igbp->queueBuffer(slot, qbi, &qbo), OK);
26452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
26552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                // If the slot is reused then we can make sure the previous graphic buffer is
26652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                // displayed (consumed), so we could returned the graphic buffer.
26752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                pendingDisplayBuffers[slot].swap(output);
26852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
26952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2703760d5fdd7e60b68ed599d7322e2599efe7a13c9Johny Lin            bool eos = work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM;
271cd56fe7ad767762950d20582daf9d646d916f10bPin-chih Lin            // input buffer should be reset in component side.
272cd56fe7ad767762950d20582daf9d646d916f10bPin-chih Lin            CHECK_EQ(work->input.buffers.size(), 1u);
273cd56fe7ad767762950d20582daf9d646d916f10bPin-chih Lin            CHECK(work->input.buffers.front() == nullptr);
27452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            work->worklets.clear();
2752a2b90179d72e158c74982599752c92aac9029deLajos Molnar            work->workletsProcessed = 0;
27652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
2773760d5fdd7e60b68ed599d7322e2599efe7a13c9Johny Lin            if (eos) {
27852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                running.store(false);  // stop the thread
27952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
28052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
28152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            ULock l(mQueueLock);
28252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            mWorkQueue.emplace_back(std::move(work));
28352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            mQueueCondition.notify_all();
28452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
28552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    });
28652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
28752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    long numFrames = 0;
28852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
28952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (;;) {
29052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        size_t size = 0u;
291a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        void* data = nullptr;
29252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        int64_t timestamp = 0u;
2937291a48a6117a6c67c6e4b776fe660e4ed9ef02bDongwon Kang        MediaBufferBase* buffer = nullptr;
29452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        sp<ABuffer> csd;
29552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (!csds.empty()) {
29652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            csd = std::move(csds.front());
29752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            csds.pop_front();
29852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            size = csd->size();
29952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            data = csd->data();
30052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        } else {
30152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            status_t err = source->read(&buffer);
30252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (err != OK) {
30352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                CHECK(buffer == nullptr);
30452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
30552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                if (err == INFO_FORMAT_CHANGED) {
30652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                    continue;
30752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                }
30852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
30952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                break;
31052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
3111ca0d0b761fd3074c538f3d31487f1b524e096daPin-chih Lin            MetaDataBase& meta = buffer->meta_data();
312ac29bf870c419dc38903896c50844b736fa8540eMarco Nelissen            CHECK(meta.findInt64(kKeyTime, &timestamp));
31352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
31452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            size = buffer->size();
31552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            data = buffer->data();
31652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
31752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
31852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // Prepare C2Work
31952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
32052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::unique_ptr<C2Work> work;
32152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        while (!work) {
32252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            ULock l(mQueueLock);
32352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (!mWorkQueue.empty()) {
32452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                work = std::move(mWorkQueue.front());
32552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                mWorkQueue.pop_front();
32652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            } else {
32752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                mQueueCondition.wait_for(l, 100ms);
32852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
32952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
3302a2b90179d72e158c74982599752c92aac9029deLajos Molnar        work->input.flags = static_cast<C2FrameData::flags_t>(0);
33152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.ordinal.timestamp = timestamp;
3322a2b90179d72e158c74982599752c92aac9029deLajos Molnar        work->input.ordinal.frameIndex = numFrames;
33352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
33452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // Allocate input buffer.
33552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::shared_ptr<C2LinearBlock> block;
33652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        mLinearBlockPool->fetchLinearBlock(
33720d1a263e74399f3a93e01bbe24db5b0066af653Johny Lin                size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
33852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        C2WriteView view = block->map().get();
33952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (view.error() != C2_OK) {
34052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            fprintf(stderr, "C2LinearBlock::map() failed : %d\n", view.error());
34152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            break;
34252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
34352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        memcpy(view.base(), data, size);
34452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
34552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.buffers.clear();
34652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->input.buffers.emplace_back(new C2VDALinearBuffer(std::move(block)));
34752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->worklets.clear();
34852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        work->worklets.emplace_back(new C2Worklet);
34952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
35052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        std::list<std::unique_ptr<C2Work>> items;
35152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        items.push_back(std::move(work));
35252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
35352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        // DO THE DECODING
35452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        component->queue_nb(&items);
35552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
35652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (buffer) {
35752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            buffer->release();
35852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
35952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        ++numFrames;
36052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
361a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin    component->drain_nb(C2Component::DRAIN_COMPONENT_WITH_EOS);
36252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
36352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    surfaceThread.join();
36452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
36552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    source->stop();
36652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    component->stop();
36752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    printf("finished...\n");
36852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return OK;
36952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
37052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
37152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}  // namespace
37252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
37352bffe176c343075c196c072aa7924de3abdd1b5Johny Linstatic bool getMediaSourceFromFile(const char* filename, sp<IMediaSource>* source) {
37452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    source->clear();
37552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
3760deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin    sp<DataSource> dataSource =
3770deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin            DataSourceFactory::CreateFromURI(nullptr /* httpService */, filename);
37852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
37952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (dataSource == nullptr) {
38052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "Unable to create data source.\n");
38152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return false;
38252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
38352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
3840deb659ab57ad7d9bac1c025cb5dd182946bc9f8Johny Lin    sp<IMediaExtractor> extractor = MediaExtractorFactory::Create(dataSource);
38552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (extractor == nullptr) {
38652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "could not create extractor.\n");
38752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return false;
38852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
38952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
3909be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    std::string expectedMime;
3919be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    if (kComponentName == kH264DecoderName) {
3929be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        expectedMime = "video/avc";
3939be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    } else if (kComponentName == kVP8DecoderName) {
3949be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        expectedMime = "video/x-vnd.on2.vp8";
39595d0e47610746d8c8444051e42413f6c0d454817Johny Lin    } else if (kComponentName == kVP9DecoderName) {
39695d0e47610746d8c8444051e42413f6c0d454817Johny Lin        expectedMime = "video/x-vnd.on2.vp9";
3979be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    } else {
3989be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        fprintf(stderr, "unrecognized component name: %s\n", kComponentName.c_str());
3999be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        return false;
4009be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    }
4019be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin
40252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (size_t i = 0, numTracks = extractor->countTracks(); i < numTracks; ++i) {
40352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        sp<MetaData> meta =
40452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                extractor->getTrackMetaData(i, MediaExtractor::kIncludeExtensiveMetaData);
40552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (meta == nullptr) {
40652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            continue;
40752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
408a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        const char* mime;
40952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        meta->findCString(kKeyMIMEType, &mime);
4109be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin        if (!strcasecmp(mime, expectedMime.c_str())) {
41152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            *source = extractor->getTrack(i);
41252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            if (*source == nullptr) {
41352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                fprintf(stderr, "It's nullptr track for track %zu.\n", i);
41452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin                return false;
41552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            }
41652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return true;
41752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
41852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
4199be5270780fda8f9e7e4aff26e10d94a1d47517bJohny Lin    fprintf(stderr, "No track found.\n");
42052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return false;
42152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
42252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
423a891f0ea984eb1175467ebe1c0ec086977464a07Johny Linstatic void usage(const char* me) {
42452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    fprintf(stderr, "usage: %s [options] [input_filename]...\n", me);
42552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    fprintf(stderr, "       -h(elp)\n");
42652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
42752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
428a891f0ea984eb1175467ebe1c0ec086977464a07Johny Linint main(int argc, char** argv) {
42952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    android::ProcessState::self()->startThreadPool();
43052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
43152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    int res;
43252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    while ((res = getopt(argc, argv, "h")) >= 0) {
43352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        switch (res) {
434a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        case 'h':
435a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        default: {
436a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin            usage(argv[0]);
437a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin            exit(1);
438a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin            break;
439a891f0ea984eb1175467ebe1c0ec086977464a07Johny Lin        }
44052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
44152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
44252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
44352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    argc -= optind;
44452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    argv += optind;
44552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
44652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    if (argc < 1) {
44752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        fprintf(stderr, "No input file specified\n");
44852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        return 1;
44952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
45052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
45152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    SimplePlayer player;
45252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
45352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    for (int k = 0; k < argc; ++k) {
45452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        sp<IMediaSource> mediaSource;
45552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (!getMediaSourceFromFile(argv[k], &mediaSource)) {
45652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            fprintf(stderr, "Unable to get media source from file: %s\n", argv[k]);
45752bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return -1;
45852bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
45952bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        if (player.play(mediaSource) != OK) {
46052bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            fprintf(stderr, "Player failed to play media source: %s\n", argv[k]);
46152bffe176c343075c196c072aa7924de3abdd1b5Johny Lin            return -1;
46252bffe176c343075c196c072aa7924de3abdd1b5Johny Lin        }
46352bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    }
46452bffe176c343075c196c072aa7924de3abdd1b5Johny Lin
46552bffe176c343075c196c072aa7924de3abdd1b5Johny Lin    return 0;
46652bffe176c343075c196c072aa7924de3abdd1b5Johny Lin}
467