Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ab211c4 authored by Kris Alder's avatar Kris Alder Committed by Automerger Merge Worker
Browse files

Merge changes I3f879fc3,Id828cef4,Ic7887d61 am: c93ffab0

Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/1519481

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ia1cb2dcfea0d2825d8b10d78aaeda3378894c4c3
parents 26bb5daf c93ffab0
Loading
Loading
Loading
Loading
+333 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 */

cc_defaults {
    name: "C2Fuzzer-defaults",

    srcs: [
        "C2Fuzzer.cpp",
    ],

    static_libs: [
        "liblog",
        "libion",
        "libfmq",
        "libbase",
        "libutils",
        "libcutils",
        "libcodec2",
        "libhidlbase",
        "libdmabufheap",
        "libcodec2_vndk",
        "libnativewindow",
        "libcodec2_soft_common",
        "libsfplugin_ccodec_utils",
        "libstagefright_foundation",
        "libstagefright_bufferpool@2.0.1",
        "android.hardware.graphics.mapper@2.0",
        "android.hardware.graphics.mapper@3.0",
        "android.hardware.media.bufferpool@2.0",
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.allocator@3.0",
        "android.hardware.graphics.bufferqueue@2.0",
    ],

    shared_libs: [
        "libui",
        "libdl",
        "libbinder",
        "libhardware",
        "libvndksupport",
        "libprocessgroup",
    ],

    cflags: [
        "-Wall",
        "-Werror",
    ],
}

cc_fuzz {
    name: "C2FuzzerAvcDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.avc.decoder\"",
    ],

    static_libs: [
        "libavcdec",
        "libcodec2_soft_avcdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerHevcDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.hevc.decoder\"",
    ],

    static_libs: [
        "libhevcdec",
        "libcodec2_soft_hevcdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerMpeg2Dec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.mpeg2.decoder\"",
    ],

    static_libs: [
        "libmpeg2dec",
        "libcodec2_soft_mpeg2dec",
    ],
}

cc_fuzz {
    name: "C2FuzzerMpeg4Dec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.mpeg4.decoder\"",
    ],

    static_libs: [
        "libstagefright_m4vh263dec",
        "libcodec2_soft_mpeg4dec",
    ],
}

cc_fuzz {
    name: "C2FuzzerH263Dec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.h263.decoder\"",
    ],

    static_libs: [
        "libstagefright_m4vh263dec",
        "libcodec2_soft_h263dec",
    ],
}

cc_fuzz {
    name: "C2FuzzerVp8Dec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.vp8.decoder\"",
    ],

    static_libs: [
        "libvpx",
        "libcodec2_soft_vp8dec",
    ],
}

cc_fuzz {
    name: "C2FuzzerVp9Dec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.vp9.decoder\"",
    ],

    static_libs: [
        "libvpx",
        "libcodec2_soft_vp9dec",
    ],
}

cc_fuzz {
    name: "C2FuzzerAacDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.aac.decoder\"",
    ],

    static_libs: [
        "libFraunhoferAAC",
        "libcodec2_soft_aacdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerAmrnbDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.amrnb.decoder\"",
    ],

    static_libs: [
        "libstagefright_amrnbdec",
        "libstagefright_amrwbdec",
        "libstagefright_amrnb_common",
        "libcodec2_soft_amrnbdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerAmrwbDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.amrwb.decoder\"",
    ],

    static_libs: [
        "libstagefright_amrnbdec",
        "libstagefright_amrwbdec",
        "libstagefright_amrnb_common",
        "libcodec2_soft_amrwbdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerFlacDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.flac.decoder\"",
    ],

    static_libs: [
        "libFLAC",
        "libstagefright_flacdec",
        "libcodec2_soft_flacdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerG711AlawDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.g711.alaw.decoder\"",
    ],

    static_libs: [
        "codecs_g711dec",
        "libcodec2_soft_g711alawdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerG711MlawDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.g711.mlaw.decoder\"",
    ],

    static_libs: [
        "codecs_g711dec",
        "libcodec2_soft_g711mlawdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerGsmDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.gsm.decoder\"",
    ],

    static_libs: [
        "libgsm",
        "libcodec2_soft_gsmdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerMp3Dec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.mp3.decoder\"",
    ],

    static_libs: [
        "libstagefright_mp3dec",
        "libcodec2_soft_mp3dec",
    ],
}

cc_fuzz {
    name: "C2FuzzerOpusDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.opus.decoder\"",
    ],

    static_libs: [
        "libopus",
        "libcodec2_soft_opusdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerRawDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.raw.decoder\"",
    ],

    static_libs: [
        "libcodec2_soft_rawdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerVorbisDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.vorbis.decoder\"",
    ],

    static_libs: [
        "libvorbisidec",
        "libcodec2_soft_vorbisdec",
    ],
}

cc_fuzz {
    name: "C2FuzzerXaacDec",
    defaults: ["C2Fuzzer-defaults"],

    cflags: [
        "-DC2COMPONENTNAME=\"c2.android.xaac.decoder\"",
    ],

    static_libs: [
        "libxaacdec",
        "libcodec2_soft_xaacdec",
    ],
}
+318 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *****************************************************************************
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 */
#include <stdio.h>

#include <C2Fuzzer.h>

using namespace android;

class LinearBuffer : public C2Buffer {
 public:
  explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
      : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}

  explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
      : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
};

/**
 * Handle Callback functions onWorkDone_nb(), onTripped_nb(), onError_nb() for C2 Components
 */
struct CodecListener : public C2Component::Listener {
 public:
  CodecListener(const std::function<void(std::weak_ptr<C2Component> comp,
                                         std::list<std::unique_ptr<C2Work>>& workItems)>
                    fn = nullptr)
      : callBack(fn) {}
  virtual void onWorkDone_nb(const std::weak_ptr<C2Component> comp,
                             std::list<std::unique_ptr<C2Work>> workItems) {
    if (callBack) {
      callBack(comp, workItems);
    }
  }

  virtual void onTripped_nb(const std::weak_ptr<C2Component> comp,
                            const std::vector<std::shared_ptr<C2SettingResult>> settingResults) {
    (void)comp;
    (void)settingResults;
  }

  virtual void onError_nb(const std::weak_ptr<C2Component> comp, uint32_t errorCode) {
    (void)comp;
    (void)errorCode;
  }

  std::function<void(std::weak_ptr<C2Component> comp,
                     std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
};

/**
 * Buffer source implementations to identify a frame and its size
 */
bool Codec2Fuzzer::BufferSource::searchForMarker() {
  while (true) {
    if (isMarker()) {
      return true;
    }
    --mReadIndex;
    if (mReadIndex > mSize) {
      break;
    }
  }
  return false;
}

void Codec2Fuzzer::BufferSource::parse() {
  bool isFrameAvailable = true;
  size_t bytesRemaining = mSize;
  while (isFrameAvailable) {
    isFrameAvailable = searchForMarker();
    if (isFrameAvailable) {
      size_t location = mReadIndex + kMarkerSize;
      bool isCSD = isCSDMarker(location);
      location += kMarkerSuffixSize;
      uint8_t* framePtr = const_cast<uint8_t*>(&mData[location]);
      size_t frameSize = bytesRemaining - location;
      uint32_t flags = 0;
      if (mFrameList.empty()) {
        flags |= C2FrameData::FLAG_END_OF_STREAM;
      } else if (isCSD) {
        flags |= C2FrameData::FLAG_CODEC_CONFIG;
      }
      mFrameList.emplace_back(std::make_tuple(framePtr, frameSize, flags));
      bytesRemaining -= (frameSize + kMarkerSize + kMarkerSuffixSize);
      --mReadIndex;
    }
  }
  if (mFrameList.empty()) {
    /**
     * Scenario where input data does not contain the custom frame markers.
     * Hence feed the entire data as single frame.
     */
    mFrameList.emplace_back(
        std::make_tuple(const_cast<uint8_t*>(mData), 0, C2FrameData::FLAG_END_OF_STREAM));
    mFrameList.emplace_back(
        std::make_tuple(const_cast<uint8_t*>(mData), mSize, C2FrameData::FLAG_CODEC_CONFIG));
  }
}

FrameData Codec2Fuzzer::BufferSource::getFrame() {
  FrameData frame = mFrameList.back();
  mFrameList.pop_back();
  return frame;
}

void Codec2Fuzzer::handleWorkDone(std::weak_ptr<C2Component> comp,
                                  std::list<std::unique_ptr<C2Work>>& workItems) {
  (void)comp;
  for (std::unique_ptr<C2Work>& work : workItems) {
    if (!work->worklets.empty()) {
      if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
        mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
        work->input.buffers.clear();
        work->worklets.clear();
        {
          std::unique_lock<std::mutex> lock(mQueueLock);
          mWorkQueue.push_back(std::move(work));
          mQueueCondition.notify_all();
        }
        if (mEos) {
          {
            std::lock_guard<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
          }
          mConditionalVariable.notify_one();
        }
      }
    }
  }
}

bool Codec2Fuzzer::initDecoder() {
  std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
        C2ComponentFactory::DestroyCodec2FactoryFunc>> codec2FactoryFunc;

  codec2FactoryFunc.emplace_back(std::make_tuple(C2COMPONENTNAME,
                                                &CreateCodec2Factory,
                                                &DestroyCodec2Factory));

  std::shared_ptr<C2ComponentStore> componentStore = GetTestComponentStore(codec2FactoryFunc);
  if (!componentStore) {
    return false;
  }

  std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
  if (!allocatorStore) {
    return false;
  }

  c2_status_t status =
      allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
  if (status != C2_OK) {
    return false;
  }

  mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, ++mBlockPoolId);
  if (!mLinearPool) {
    return false;
  }

  for (int32_t i = 0; i < kNumberOfC2WorkItems; ++i) {
    mWorkQueue.emplace_back(new C2Work);
  }

  status = componentStore->createComponent(C2COMPONENTNAME, &mComponent);
  if (status != C2_OK) {
    return false;
  }

  status = componentStore->createInterface(C2COMPONENTNAME, &mInterface);
  if (status != C2_OK) {
    return false;
  }

  C2ComponentKindSetting kind;
  C2ComponentDomainSetting domain;
  status = mInterface->query_vb({&kind, &domain}, {}, C2_MAY_BLOCK, nullptr);
  if (status != C2_OK) {
    return false;
  }

  std::vector<C2Param*> configParams;
  if (domain.value == DOMAIN_VIDEO) {
    C2StreamPictureSizeInfo::input inputSize(0u, kWidthOfVideo, kHeightOfVideo);
    configParams.push_back(&inputSize);
  } else if (domain.value == DOMAIN_AUDIO) {
    C2StreamSampleRateInfo::output sampleRateInfo(0u, kSamplingRateOfAudio);
    C2StreamChannelCountInfo::output channelCountInfo(0u, kChannelsOfAudio);
    configParams.push_back(&sampleRateInfo);
    configParams.push_back(&channelCountInfo);
  }

  mListener.reset(new CodecListener(
      [this](std::weak_ptr<C2Component> comp, std::list<std::unique_ptr<C2Work>>& workItems) {
        handleWorkDone(comp, workItems);
      }));
  if (!mListener) {
    return false;
  }

  status = mComponent->setListener_vb(mListener, C2_DONT_BLOCK);
  if (status != C2_OK) {
    return false;
  }

  std::vector<std::unique_ptr<C2SettingResult>> failures;
  componentStore->config_sm(configParams, &failures);
  if (failures.size() != 0) {
    return false;
  }

  status = mComponent->start();
  if (status != C2_OK) {
    return false;
  }

  return true;
}

void Codec2Fuzzer::deInitDecoder() {
  mComponent->stop();
  mComponent->reset();
  mComponent->release();
  mComponent = nullptr;
}

void Codec2Fuzzer::decodeFrames(const uint8_t* data, size_t size) {
  mBufferSource = new BufferSource(data, size);
  if (!mBufferSource) {
    return;
  }
  mBufferSource->parse();
  c2_status_t status = C2_OK;
  size_t numFrames = 0;
  while (!mBufferSource->isEos()) {
    uint8_t* frame = nullptr;
    size_t frameSize = 0;
    FrameData frameData = mBufferSource->getFrame();
    frame = std::get<0>(frameData);
    frameSize = std::get<1>(frameData);

    std::unique_ptr<C2Work> work;
    {
      std::unique_lock<std::mutex> lock(mQueueLock);
      if (mWorkQueue.empty()) mQueueCondition.wait_for(lock, kC2FuzzerTimeOut);
      if (!mWorkQueue.empty()) {
        work.swap(mWorkQueue.front());
        mWorkQueue.pop_front();
      } else {
        return;
      }
    }

    work->input.flags = (C2FrameData::flags_t)std::get<2>(frameData);
    work->input.ordinal.timestamp = 0;
    work->input.ordinal.frameIndex = ++numFrames;
    work->input.buffers.clear();
    int32_t alignedSize = C2FUZZER_ALIGN(frameSize, PAGE_SIZE);

    std::shared_ptr<C2LinearBlock> block;
    status = mLinearPool->fetchLinearBlock(
        alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
    if (status != C2_OK || block == nullptr) {
      return;
    }

    C2WriteView view = block->map().get();
    if (view.error() != C2_OK) {
      return;
    }
    memcpy(view.base(), frame, frameSize);
    work->input.buffers.emplace_back(new LinearBuffer(block, frameSize));
    work->worklets.clear();
    work->worklets.emplace_back(new C2Worklet);

    std::list<std::unique_ptr<C2Work>> items;
    items.push_back(std::move(work));
    status = mComponent->queue_nb(&items);
    if (status != C2_OK) {
      return;
    }
  }
  std::unique_lock<std::mutex> waitForDecodeComplete(mDecodeCompleteMutex);
  mConditionalVariable.wait_for(waitForDecodeComplete, kC2FuzzerTimeOut, [this] { return mEos; });
  std::list<std::unique_ptr<C2Work>> c2flushedWorks;
  mComponent->flush_sm(C2Component::FLUSH_COMPONENT, &c2flushedWorks);
  delete mBufferSource;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  if (size < 1) {
    return 0;
  }
  Codec2Fuzzer* codec = new Codec2Fuzzer();
  if (!codec) {
    return 0;
  }
  if (codec->initDecoder()) {
    codec->decodeFrames(data, size);
  }
  delete codec;
  return 0;
}
+114 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *****************************************************************************
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 */
#ifndef __C2FUZZER_H__
#define __C2FUZZER_H__

#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2Component.h>
#include <C2Config.h>
#include <C2PlatformSupport.h>

using namespace std::chrono_literals;

extern "C" ::C2ComponentFactory* CreateCodec2Factory();
extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory);

namespace android {

#define C2FUZZER_ALIGN(_sz, _align) (((_sz) + ((_align)-1)) & ~((_align)-1))

constexpr std::chrono::milliseconds kC2FuzzerTimeOut = 5000ms;
constexpr int32_t kNumberOfC2WorkItems = 8;
constexpr uint32_t kWidthOfVideo = 3840;
constexpr uint32_t kHeightOfVideo = 2160;
constexpr uint32_t kSamplingRateOfAudio = 48000;
constexpr uint32_t kChannelsOfAudio = 8;

typedef std::tuple<uint8_t*, size_t, uint32_t> FrameData;

class Codec2Fuzzer {
 public:
  Codec2Fuzzer() = default;
  ~Codec2Fuzzer() { deInitDecoder(); }
  bool initDecoder();
  void deInitDecoder();
  void decodeFrames(const uint8_t* data, size_t size);

  void handleWorkDone(std::weak_ptr<C2Component> comp,
                      std::list<std::unique_ptr<C2Work>>& workItems);

 private:
  class BufferSource {
   public:
    BufferSource(const uint8_t* data, size_t size)
        : mData(data), mSize(size), mReadIndex(size - kMarkerSize) {}
    ~BufferSource() {
      mData = nullptr;
      mSize = 0;
      mReadIndex = 0;
      mFrameList.clear();
    }
    bool isEos() { return mFrameList.empty(); }
    void parse();
    FrameData getFrame();

   private:
    bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); }

    bool isCSDMarker(size_t position) {
      return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0);
    }

    bool searchForMarker();

    const uint8_t* mData = nullptr;
    size_t mSize = 0;
    size_t mReadIndex = 0;
    std::vector<FrameData> mFrameList;
    static constexpr uint8_t kMarker[] = "_MARK";
    static constexpr uint8_t kCsdMarkerSuffix[] = "_H_";
    static constexpr uint8_t kFrameMarkerSuffix[] = "_F_";
    // All markers should be 5 bytes long ( sizeof '_MARK' which is 5)
    static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1);
    // All marker types should be 3 bytes long ('_H_', '_F_')
    static constexpr size_t kMarkerSuffixSize = 3;
  };

  BufferSource* mBufferSource;
  bool mEos = false;
  C2BlockPool::local_id_t mBlockPoolId;

  std::shared_ptr<C2BlockPool> mLinearPool;
  std::shared_ptr<C2Allocator> mLinearAllocator;
  std::shared_ptr<C2Component::Listener> mListener;
  std::shared_ptr<C2Component> mComponent;
  std::shared_ptr<C2ComponentInterface> mInterface;
  std::mutex mQueueLock;
  std::condition_variable mQueueCondition;
  std::list<std::unique_ptr<C2Work>> mWorkQueue;
  std::mutex mDecodeCompleteMutex;
  std::condition_variable mConditionalVariable;
};

}  // namespace android

#endif  // __C2FUZZER_H__
+85 −12

File changed.

Preview size limit exceeded, changes collapsed.

+9 −0
Original line number Diff line number Diff line
@@ -143,6 +143,15 @@ c2_status_t CreateCodec2BlockPool(
 */
std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore();

/**
 * Returns the platform component store.
 * NOTE: For testing only
 * \retval nullptr if the platform component store could not be obtained
 */
std::shared_ptr<C2ComponentStore> GetTestComponentStore(
        std::vector<std::tuple<C2String, C2ComponentFactory::CreateCodec2FactoryFunc,
        C2ComponentFactory::DestroyCodec2FactoryFunc>>);

/**
 * Sets the preferred component store in this process for the sole purpose of accessing its
 * interface. If this is not called, the default IComponentStore HAL (if exists) is the preferred