1033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/*
2033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Copyright (C) 2018 The Android Open Source Project
3033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
4033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Licensed under the Apache License, Version 2.0 (the "License");
5033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * you may not use this file except in compliance with the License.
6033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * You may obtain a copy of the License at
7033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
8033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *      http://www.apache.org/licenses/LICENSE-2.0
9033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim *
10033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * Unless required by applicable law or agreed to in writing, software
11033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * distributed under the License is distributed on an "AS IS" BASIS,
12033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * See the License for the specific language governing permissions and
14033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * limitations under the License.
15033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim */
16033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
17d087ee640c4664516a25cec687a76b31bb62b2e1Lajos Molnar//#define LOG_NDEBUG 0
18b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo#ifdef MPEG4
19b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo  #define LOG_TAG "C2SoftMpeg4Dec"
20b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo#else
21b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo  #define LOG_TAG "C2SoftH263Dec"
22b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo#endif
23d087ee640c4664516a25cec687a76b31bb62b2e1Lajos Molnar#include <log/log.h>
24033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
25d087ee640c4664516a25cec687a76b31bb62b2e1Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
26d087ee640c4664516a25cec687a76b31bb62b2e1Lajos Molnar#include <media/stagefright/foundation/MediaDefs.h>
27033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
28d087ee640c4664516a25cec687a76b31bb62b2e1Lajos Molnar#include <C2Debug.h>
29033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include <C2PlatformSupport.h>
3072dc0b6eea5a305d58537dcd2ee28e23c72b6e44Lajos Molnar#include <SimpleC2Interface.h>
31033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
32d087ee640c4664516a25cec687a76b31bb62b2e1Lajos Molnar#include "C2SoftMpeg4Dec.h"
33033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#include "mp4dec_api.h"
34033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
35033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimnamespace android {
36033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
37033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#ifdef MPEG4
385c2c3d46fc95a4e08dbd7a7a3304e389d85faa86Lajos Molnarconstexpr char COMPONENT_NAME[] = "c2.android.mpeg4.decoder";
39033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#else
405c2c3d46fc95a4e08dbd7a7a3304e389d85faa86Lajos Molnarconstexpr char COMPONENT_NAME[] = "c2.android.h263.decoder";
41033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#endif
42033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
435dd9c17181139af91599b5fd2f84981616447d03Manisha Jajooclass C2SoftMpeg4Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
44b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoopublic:
45b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
465dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        : SimpleInterface<void>::BaseParams(
475dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                helper,
485dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                COMPONENT_NAME,
495dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                C2Component::KIND_DECODER,
505dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                C2Component::DOMAIN_VIDEO,
51033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#ifdef MPEG4
525dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                MEDIA_MIMETYPE_VIDEO_MPEG4
53033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#else
545dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                MEDIA_MIMETYPE_VIDEO_H263
55033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#endif
565dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                ) {
575dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        noPrivateBuffers(); // TODO: account for our buffers here
585dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        noInputReferences();
595dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        noOutputReferences();
605dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        noInputLatency();
615dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        noTimeStretch();
625dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
635dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        // TODO: output latency and reordering
64b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo
65b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        addParameter(
665dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
675dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL))
68b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                .build());
69b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo
70b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        addParameter(
715dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
725dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withDefault(new C2StreamPictureSizeInfo::output(0u, 176, 144))
73b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                .withFields({
74b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo#ifdef MPEG4
75b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                    C2F(mSize, width).inRange(16, 352, 2),
76b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                    C2F(mSize, height).inRange(16, 288, 2),
77b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo#else
78b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                    C2F(mSize, width).inRange(16, 352, 16),
79b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                    C2F(mSize, height).inRange(16, 288, 16),
80b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo#endif
81b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                })
82b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                .withSetter(SizeSetter)
83b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                .build());
845dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
855dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo#ifdef MPEG4
865dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        addParameter(
875dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
885dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withDefault(new C2StreamProfileLevelInfo::input(0u,
895dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                        C2Config::PROFILE_MP4V_SIMPLE, C2Config::LEVEL_MP4V_3))
905dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withFields({
915dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    C2F(mProfileLevel, profile).equalTo(
925dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::PROFILE_MP4V_SIMPLE),
935dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    C2F(mProfileLevel, level).oneOf({
945dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_MP4V_0,
955dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_MP4V_0B,
965dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_MP4V_1,
975dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_MP4V_2,
985dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_MP4V_3})
995dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                })
1005dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withSetter(ProfileLevelSetter, mSize)
1015dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .build());
1025dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo#else
1035dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        addParameter(
1045dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
1055dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withDefault(new C2StreamProfileLevelInfo::input(0u,
1065dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                        C2Config::PROFILE_H263_BASELINE, C2Config::LEVEL_H263_30))
1075dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withFields({
1085dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    C2F(mProfileLevel, profile).oneOf({
1095dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::PROFILE_H263_BASELINE,
1105dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::PROFILE_H263_ISWV2}),
1115dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    C2F(mProfileLevel, level).oneOf({
1125dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_H263_10,
1135dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_H263_20,
1145dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_H263_30,
1155dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_H263_40,
1165dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                            C2Config::LEVEL_H263_45})
1175dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                })
1185dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withSetter(ProfileLevelSetter, mSize)
1195dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .build());
1205dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo#endif
1215dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
1225dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() };
1235dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
1245dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo            C2StreamColorInfo::output::AllocShared(
1255dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    1u, 0u, 8u /* bitDepth */, C2Color::YUV_420);
1265dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
1275dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
1285dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        defaultColorInfo =
1295dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo            C2StreamColorInfo::output::AllocShared(
1305dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    { C2ChromaOffsetStruct::ITU_YUV_420_0() },
1315dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                    0u, 8u /* bitDepth */, C2Color::YUV_420);
132118d815d2cd1820dfaff033f5ff1217c4f57f033Lajos Molnar        helper->addStructDescriptors<C2ChromaOffsetStruct>();
1335dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
1345dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        addParameter(
1355dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
1365dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withConstValue(defaultColorInfo)
1375dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .build());
1385dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
1395dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        // TODO: support more formats?
1405dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        addParameter(
1415dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
1425dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .withConstValue(new C2StreamPixelFormatInfo::output(
1435dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                                     0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
1445dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                .build());
1455dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo    }
1465dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo
1475dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo    static C2R SizeSetter(bool mayBlock, const C2P<C2VideoSizeStreamInfo::output> &oldMe,
1485dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                          C2P<C2VideoSizeStreamInfo::output> &me) {
1495dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        (void)mayBlock;
1505dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        C2R res = C2R::Ok();
1515dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
1525dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
1535dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo            me.set().width = oldMe.v.width;
1545dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        }
1555dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
1565dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
1575dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo            me.set().height = oldMe.v.height;
1585dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        }
1595dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        return res;
160b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    }
161b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo
1625dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo    static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
1635dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo                                  const C2P<C2StreamPictureSizeInfo::output> &size) {
164b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        (void)mayBlock;
1655dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        (void)size;
1665dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        (void)me;  // TODO: validate
1675dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo        return C2R::Ok();
168b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    }
169b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo
170b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajooprivate:
1715dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo    std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
172b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    std::shared_ptr<C2VideoSizeStreamInfo::output> mSize;
1735dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo    std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
1745dd9c17181139af91599b5fd2f84981616447d03Manisha Jajoo    std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
175b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo};
176033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
177b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha JajooC2SoftMpeg4Dec::C2SoftMpeg4Dec(
178b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        const char *name,
179b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        c2_node_id_t id,
180b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        const std::shared_ptr<IntfImpl> &intfImpl)
181b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
182b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo      mIntf(intfImpl),
183033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim      mDecHandle(nullptr),
1847c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo      mOutputBuffer{},
1857c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo      mInitialized(false) {
186033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
187033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
188033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik KimC2SoftMpeg4Dec::~C2SoftMpeg4Dec() {
189033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    onRelease();
190033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
191033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
192033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimc2_status_t C2SoftMpeg4Dec::onInit() {
193033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    status_t err = initDecoder();
194033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return err == OK ? C2_OK : C2_CORRUPTED;
195033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
196033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
197033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimc2_status_t C2SoftMpeg4Dec::onStop() {
198033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mInitialized) {
1997c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo        if (mDecHandle) {
2007c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            PVCleanUpVideoDecoder(mDecHandle);
2017c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo        }
202033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mInitialized = false;
203033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
204033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
205033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mOutputBuffer[i]) {
206033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            free(mOutputBuffer[i]);
207033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mOutputBuffer[i] = nullptr;
208033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
209033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
210033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mNumSamplesOutput = 0;
211033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mFramesConfigured = false;
212033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSignalledOutputEos = false;
213033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSignalledError = false;
214033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
215033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return C2_OK;
216033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
217033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
218033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid C2SoftMpeg4Dec::onReset() {
2197c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo    (void)onStop();
2207c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo    (void)onInit();
221033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
222033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
223033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid C2SoftMpeg4Dec::onRelease() {
224033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mInitialized) {
2257c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo        if (mDecHandle) {
2267c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            PVCleanUpVideoDecoder(mDecHandle);
2277c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            delete mDecHandle;
2287c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            mDecHandle = nullptr;
2297c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo        }
230033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mInitialized = false;
231033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
232033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mOutBlock) {
233033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mOutBlock.reset();
234033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
235033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
236033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mOutputBuffer[i]) {
237033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            free(mOutputBuffer[i]);
238033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mOutputBuffer[i] = nullptr;
239033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
240033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
241033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
242033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
243033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimc2_status_t C2SoftMpeg4Dec::onFlush_sm() {
244033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mInitialized) {
2457c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo        if (PV_TRUE != PVResetVideoDecoder(mDecHandle)) {
2467c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            return C2_CORRUPTED;
2477c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo        }
248033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
249033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSignalledOutputEos = false;
250033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSignalledError = false;
251033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return C2_OK;
252033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
253033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
254033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatus_t C2SoftMpeg4Dec::initDecoder() {
255033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#ifdef MPEG4
256033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mIsMpeg4 = true;
257033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#else
258033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mIsMpeg4 = false;
259033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim#endif
260033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!mDecHandle) {
261033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mDecHandle = new tagvideoDecControls;
262033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
263033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    memset(mDecHandle, 0, sizeof(tagvideoDecControls));
264033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
265033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /* TODO: bring these values to 352 and 288. It cannot be done as of now
266033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * because, h263 doesn't seem to allow port reconfiguration. In OMX, the
267033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * problem of larger width and height than default width and height is
268033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * overcome by adaptivePlayBack() api call. This call gets width and height
269033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * information from extractor. Such a thing is not possible here.
270033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim     * So we are configuring to larger values.*/
271033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mWidth = 1408;
272033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mHeight = 1152;
273033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mNumSamplesOutput = 0;
274033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mInitialized = false;
275033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mFramesConfigured = false;
276033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSignalledOutputEos = false;
277033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mSignalledError = false;
278033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
279033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return OK;
280033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
281033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
282033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid fillEmptyWork(const std::unique_ptr<C2Work> &work) {
283033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint32_t flags = 0;
284033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
285033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        flags |= C2FrameData::FLAG_END_OF_STREAM;
286033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGV("signalling eos");
287033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
288033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
289033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->worklets.front()->output.buffers.clear();
290033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->worklets.front()->output.ordinal = work->input.ordinal;
291033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->workletsProcessed = 1u;
292033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
293033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
294033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid C2SoftMpeg4Dec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
295033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mOutBlock),
296033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                                                           C2Rect(mWidth, mHeight));
297033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    mOutBlock = nullptr;
298033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
299033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t flags = 0;
300033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
301033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
302033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            flags |= C2FrameData::FLAG_END_OF_STREAM;
303033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGV("signalling eos");
304033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
305033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
306033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->worklets.front()->output.buffers.clear();
307033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->worklets.front()->output.buffers.push_back(buffer);
308033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->worklets.front()->output.ordinal = work->input.ordinal;
309033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->workletsProcessed = 1u;
310033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    };
311033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
312033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        fillWork(work);
313033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    } else {
314033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        finish(index, fillWork);
315033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
316033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
317033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
318033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimc2_status_t C2SoftMpeg4Dec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
319033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!mDecHandle) {
320033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGE("not supposed to be here, invalid decoder context");
321033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return C2_CORRUPTED;
322033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
323033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
324033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint32_t outSize = align(mWidth, 16) * align(mHeight, 16) * 3 / 2;
325033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
326033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!mOutputBuffer[i]) {
327033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mOutputBuffer[i] = (uint8_t *)malloc(outSize * sizeof(uint8_t));
3287c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            if (!mOutputBuffer[i]) {
3297c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo                return C2_NO_MEMORY;
3307c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo            }
331033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
332033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
333033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mOutBlock &&
334033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            (mOutBlock->width() != align(mWidth, 16) || mOutBlock->height() != mHeight)) {
335033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mOutBlock.reset();
336033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
337033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!mOutBlock) {
338033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t format = HAL_PIXEL_FORMAT_YV12;
339033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
340033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight, format, usage, &mOutBlock);
341033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (err != C2_OK) {
342033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("fetchGraphicBlock for Output failed with status %d", err);
343033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return err;
344033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
345033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGV("provided (%dx%d) required (%dx%d)",
346033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim              mOutBlock->width(), mOutBlock->height(), mWidth, mHeight);
347033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
348033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return C2_OK;
349033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
350033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
351033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimbool C2SoftMpeg4Dec::handleResChange(const std::unique_ptr<C2Work> &work) {
352033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint32_t disp_width, disp_height;
353033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    PVGetVideoDimensions(mDecHandle, (int32 *)&disp_width, (int32 *)&disp_height);
354033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
355033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint32_t buf_width, buf_height;
356033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    PVGetBufferDimensions(mDecHandle, (int32 *)&buf_width, (int32 *)&buf_height);
357033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
358033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK_LE(disp_width, buf_width);
359033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    CHECK_LE(disp_height, buf_height);
360033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
361033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("display size (%dx%d), buffer size (%dx%d)",
362033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim           disp_width, disp_height, buf_width, buf_height);
363033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
364033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool resChanged = false;
365033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (disp_width != mWidth || disp_height != mHeight) {
366033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mWidth = disp_width;
367033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mHeight = disp_height;
368033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        resChanged = true;
369033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
370033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (mOutputBuffer[i]) {
371033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                free(mOutputBuffer[i]);
372033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mOutputBuffer[i] = nullptr;
373033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
374033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
375033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
376033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!mIsMpeg4) {
377033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            PVCleanUpVideoDecoder(mDecHandle);
378033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
379033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            uint8_t *vol_data[1]{};
380033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            int32_t vol_size = 0;
381033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
382033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            if (!PVInitVideoDecoder(
383033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mDecHandle, vol_data, &vol_size, 1, mWidth, mHeight, H263_MODE)) {
384033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                ALOGE("Error in PVInitVideoDecoder H263_MODE while resChanged was set to true");
385033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                work->result = C2_CORRUPTED;
386033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mSignalledError = true;
387033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                return true;
388033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            }
389033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
390033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mFramesConfigured = false;
391033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
392033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return resChanged;
393033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
394033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
395033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim/* TODO: can remove temporary copy after library supports writing to display
396033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim * buffer Y, U and V plane pointers using stride info. */
397033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimstatic void copyOutputBufferToYV12Frame(uint8_t *dst, uint8_t *src, size_t dstYStride,
398033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                                        size_t srcYStride, uint32_t width, uint32_t height) {
399033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t dstUVStride = align(dstYStride / 2, 16);
400033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t srcUVStride = srcYStride / 2;
401033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint8_t *srcStart = src;
402033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint8_t *dstStart = dst;
403033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t vStride = align(height, 16);
404033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    for (size_t i = 0; i < height; ++i) {
405033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         memcpy(dst, src, width);
406033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         src += srcYStride;
407033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         dst += dstYStride;
408033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
409033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /* U buffer */
410033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    src = srcStart + vStride * srcYStride;
411033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
412033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    for (size_t i = 0; i < height / 2; ++i) {
413033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         memcpy(dst, src, width / 2);
414033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         src += srcUVStride;
415033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         dst += dstUVStride;
416033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
417033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    /* V buffer */
418033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    src = srcStart + vStride * srcYStride * 5 / 4;
419033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    dst = dstStart + (dstYStride * height);
420033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    for (size_t i = 0; i < height / 2; ++i) {
421033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         memcpy(dst, src, width / 2);
422033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         src += srcUVStride;
423033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim         dst += dstUVStride;
424033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
425033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
426033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
427033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimvoid C2SoftMpeg4Dec::process(
428033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const std::unique_ptr<C2Work> &work,
429033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const std::shared_ptr<C2BlockPool> &pool) {
430033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->result = C2_OK;
431033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    work->workletsProcessed = 0u;
432b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    work->worklets.front()->output.configUpdate.clear();
433033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (mSignalledError || mSignalledOutputEos) {
434033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        work->result = C2_BAD_VALUE;
435033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
436033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
437033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
43845c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim    size_t inOffset = 0u;
43945c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim    size_t inSize = 0u;
440033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
44145c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim    C2ReadView rView = mDummyReadView;
44245c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim    if (!work->input.buffers.empty()) {
44345c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim        rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
44445c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim        inSize = rView.capacity();
44545c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim        if (inSize && rView.error()) {
44645c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim            ALOGE("read view map failed %d", rView.error());
44745c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim            work->result = C2_CORRUPTED;
44845c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim            return;
44945c52538eab8ff337687d374f657cff5d6c51912Wonsik Kim        }
450033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
451033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
452033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          inSize, (int)work->input.ordinal.timestamp.peeku(),
453033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim          (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
454033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
455033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
456033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (inSize == 0) {
457033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        fillEmptyWork(work);
458033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (eos) {
459033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledOutputEos = true;
460033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
461033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return;
462033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
463033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
464033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
465033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    uint32_t *start_code = (uint32_t *)bitstream;
466033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    bool volHeader = *start_code == 0xB0010000;
467033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (volHeader) {
468033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        PVCleanUpVideoDecoder(mDecHandle);
469033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mInitialized = false;
470033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
471033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
472033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (!mInitialized) {
473033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint8_t *vol_data[1]{};
474033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t vol_size = 0;
475033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
476033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
477033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (codecConfig || volHeader) {
478033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            vol_data[0] = bitstream;
479033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            vol_size = inSize;
480033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
481033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        MP4DecodingMode mode = (mIsMpeg4) ? MPEG4_MODE : H263_MODE;
482033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
483033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!PVInitVideoDecoder(
484033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mDecHandle, vol_data, &vol_size, 1,
485033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                mWidth, mHeight, mode)) {
486033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("PVInitVideoDecoder failed. Unsupported content?");
487033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
488033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
489033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
490033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
491033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        mInitialized = true;
492033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        MP4DecodingMode actualMode = PVGetDecBitstreamMode(mDecHandle);
493033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mode != actualMode) {
494033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Decoded mode not same as actual mode of the decoder");
495033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
496033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
497033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
498033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
499033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
500033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        PVSetPostProcType(mDecHandle, 0);
501b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        if (handleResChange(work)) {
502b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            ALOGI("Setting width and height");
503b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight);
504b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            std::vector<std::unique_ptr<C2SettingResult>> failures;
505b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
506b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            if (err == OK) {
507b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                work->worklets.front()->output.configUpdate.push_back(
508b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                    C2Param::Copy(size));
509b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            } else {
510b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                ALOGE("Config update size failed");
511b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                mSignalledError = true;
512b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                work->result = C2_CORRUPTED;
513b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                return;
514b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            }
515b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        }
516033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (codecConfig) {
517033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            fillEmptyWork(work);
518033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
519033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
520033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
521033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
522033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    size_t inPos = 0;
523033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    while (inPos < inSize) {
524033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        c2_status_t err = ensureDecoderState(pool);
525033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (C2_OK != err) {
526033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
527033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = err;
528033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
529033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
530033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        C2GraphicView wView = mOutBlock->map().get();
531033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (wView.error()) {
532033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("graphic view map failed %d", wView.error());
533033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
534033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
535033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
536033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
537033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t outSize = align(mWidth, 16) * align(mHeight, 16) * 3 / 2;
538033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t yFrameSize = sizeof(uint8) * mDecHandle->size;
539033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (outSize < yFrameSize * 3 / 2){
540033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("Too small output buffer: %d bytes", outSize);
541033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_NO_MEMORY;
542033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
543033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
544033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
545033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
546033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (!mFramesConfigured) {
547033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            PVSetReferenceYUV(mDecHandle,mOutputBuffer[1]);
548033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mFramesConfigured = true;
549033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
550033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
551033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // Need to check if header contains new info, e.g., width/height, etc.
552033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        VopHeaderInfo header_info;
553033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t useExtTimestamp = (inPos == 0);
554033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        int32_t tmpInSize = (int32_t)inSize;
555033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint8_t *bitstreamTmp = bitstream;
556033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t timestamp = workIndex;
557033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (PVDecodeVopHeader(
558033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mDecHandle, &bitstreamTmp, &timestamp, &tmpInSize,
559033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    &header_info, &useExtTimestamp,
560033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                    mOutputBuffer[mNumSamplesOutput & 1]) != PV_TRUE) {
561033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("failed to decode vop header.");
562033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
563033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
564033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
565033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
566033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
567033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // H263 doesn't have VOL header, the frame size information is in short header, i.e. the
568033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        // decoder may detect size change after PVDecodeVopHeader.
569033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        bool resChange = handleResChange(work);
570033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (mIsMpeg4 && resChange) {
571033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
572033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
573033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
574033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        } else if (resChange) {
575b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            ALOGI("Setting width and height");
576b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight);
577b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            std::vector<std::unique_ptr<C2SettingResult>> failures;
578b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
579b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            if (err == OK) {
580b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(size));
581b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            } else {
582b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                ALOGE("Config update size failed");
583b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                mSignalledError = true;
584b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                work->result = C2_CORRUPTED;
585b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                return;
586b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo            }
587033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            continue;
588033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
589033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
590033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (PVDecodeVopBody(mDecHandle, &tmpInSize) != PV_TRUE) {
591033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGE("failed to decode video frame.");
592033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
593033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
594033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
595033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
596033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (handleResChange(work)) {
597033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            work->result = C2_CORRUPTED;
598033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            mSignalledError = true;
599033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            return;
600033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
601033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
602033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint8_t *outputBufferY = wView.data()[C2PlanarLayout::PLANE_Y];
603033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        (void)copyOutputBufferToYV12Frame(outputBufferY, mOutputBuffer[mNumSamplesOutput & 1],
604033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                                          wView.width(), align(mWidth, 16), mWidth, mHeight);
605033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
606033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        inPos += inSize - (size_t)tmpInSize;
607033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        finishWork(workIndex, work);
608033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ++mNumSamplesOutput;
609033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        if (inSize - inPos != 0) {
610033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            ALOGD("decoded frame, ignoring further trailing bytes %d",
611033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim                  (int)inSize - (int)inPos);
612033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            break;
613033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        }
614033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
615033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
616033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
617033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimc2_status_t C2SoftMpeg4Dec::drain(
618033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        uint32_t drainMode,
619033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        const std::shared_ptr<C2BlockPool> &pool) {
6207c288ff40324950abc6366aac709844325b3e0d8Manisha Jajoo    (void)pool;
621033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (drainMode == NO_DRAIN) {
622033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGW("drain with NO_DRAIN: no-op");
623033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return C2_OK;
624033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
625033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    if (drainMode == DRAIN_CHAIN) {
626033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        ALOGW("DRAIN_CHAIN not supported");
627033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return C2_OMITTED;
628033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
629033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return C2_OK;
630033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
631033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
632033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimclass C2SoftMpeg4DecFactory : public C2ComponentFactory {
633033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimpublic:
634b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    C2SoftMpeg4DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
635b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        GetCodec2PlatformComponentStore()->getParamReflector())) {
636b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    }
637b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo
638033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual c2_status_t createComponent(
639033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            c2_node_id_t id,
640033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::shared_ptr<C2Component>* const component,
641033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::function<void(C2Component*)> deleter) override {
642b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        *component = std::shared_ptr<C2Component>(
643b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                new C2SoftMpeg4Dec(COMPONENT_NAME,
644b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                                   id,
645b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                                   std::make_shared<C2SoftMpeg4Dec::IntfImpl>(mHelper)),
646b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                deleter);
647033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return C2_OK;
648033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
649033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
650033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual c2_status_t createInterface(
651033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            c2_node_id_t id,
652033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::shared_ptr<C2ComponentInterface>* const interface,
653033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim            std::function<void(C2ComponentInterface*)> deleter) override {
654b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo        *interface = std::shared_ptr<C2ComponentInterface>(
655b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                new SimpleInterface<C2SoftMpeg4Dec::IntfImpl>(
656b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                        COMPONENT_NAME, id, std::make_shared<C2SoftMpeg4Dec::IntfImpl>(mHelper)),
657b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo                deleter);
658033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim        return C2_OK;
659033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    }
660033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
661033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    virtual ~C2SoftMpeg4DecFactory() override = default;
662b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo
663b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajooprivate:
664b0d4996c67f18ede9c3d494703e3b9552d21a227Manisha Jajoo    std::shared_ptr<C2ReflectorHelper> mHelper;
665033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim};
666033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
667033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}  // namespace android
668033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
669033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" ::C2ComponentFactory* CreateCodec2Factory() {
670033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("in %s", __func__);
671033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    return new ::android::C2SoftMpeg4DecFactory();
672033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
673033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim
674033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kimextern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
675033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    ALOGV("in %s", __func__);
676033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim    delete factory;
677033ea548eec7ec220082ea6b199bf6e77f67a40dWonsik Kim}
678