瑞芯微rv1126 SDK代码基础分析---flow

手册Rockchip_Instructions_Linux_MediaServer_CN 

rkmedia source的目录结构,其中flow,stream组成为pipe,当前目录下定义了以上的基类。

.
|-- c_api
|   `-- osd
|-- ffmpeg
|-- filter
|-- flow
|-- guard
|-- live555
|   `-- server
|-- ogg
|-- rkmpp
|-- rknn
|-- rkrga
|-- stream
|   |-- audio
|   |   `-- alsa
|   |-- camera
|   `-- display
|       `-- drm_disp
`-- uvc

配置文件使用json格式。
Pipe表示一路独立的多媒体通道。
Flow表示一路多媒体通道中的一个Source/IO/Sink单元。

Flow是作为上述功能模块的再次封装,便于实现模块间的数据通信。比如有如下业务场景:
v4l2 capture video --> rga --> display

Stream表示FLow使用的处理方法。


${SDK}\external\rkmedia\include\easymedia\flow.h

${SDK}\external\rkmedia\include\easymedia\reflector.h

DECLARE_FACTORY(Flow)

#define DECLARE_FACTORY(PRODUCT)                                               \
  class PRODUCT;                                                               \
  class PRODUCT##Factory {                                                     \
  public:                                                                      \
    virtual const char *Identifier() const = 0;                                \
    static _API const char *Parse(const char *request);                        \
    virtual std::shared_ptr<PRODUCT> NewProduct(const char *param) = 0;        \
    bool AcceptRules(const char *rules) const {                                \
      std::map<std::string, std::string> map;                                  \
      if (!parse_media_param_map(rules, map))                                  \
        return false;                                                          \
      return AcceptRules(map);                                                 \
    }                                                                          \
    virtual bool                                                               \
    AcceptRules(const std::map<std::string, std::string> &map) const = 0;      \
                                                                               \
  protected:                                                                   \
    PRODUCT##Factory() = default;                                              \
    virtual ~PRODUCT##Factory() = default;                                     \
                                                                               \
  private:                                                                     \
    PRODUCT##Factory(const PRODUCT##Factory &) = delete;                       \
    PRODUCT##Factory &operator=(const PRODUCT##Factory &) = delete;            \
  };

基础代理类分析

  virtual const char *Identifier() const = 0; 虚函数,字面意思标识

static _API const char *Parse(const char *request); 解析请求字符串

${SDK}\external\tensorflow\tensorflow\contrib\lite\tools\command_line_flags.cc

bool Flag::Parse(const std::string& arg, bool* value_parsing_ok) const {
  return ParseFlag(arg, name_, value_hook_, value_parsing_ok);
}

bool ParseFlag(const std::string& arg, const std::string& flag,
               const std::function<bool(const std::string&)>& parse_func,
               bool* value_parsing_ok) {
  *value_parsing_ok = true;
  std::string flag_prefix = "--" + flag + "=";
  if (arg.find(flag_prefix) != 0) {
    return false;
  }
  bool has_value = (arg.size() >= flag_prefix.size() + 1);
  *value_parsing_ok = has_value;
  if (has_value) {
    *value_parsing_ok = parse_func(arg.substr(flag_prefix.size()));
  }
  return true;
}
bool parse_media_param_map(const char *param,
                           std::map<std::string, std::string> &map) {
  if (!param)
    return false;

  std::string token;
  std::istringstream tokenStream(param);
  while (std::getline(tokenStream, token)) {
    std::string key, value;
    std::istringstream subTokenStream(token);
    if (std::getline(subTokenStream, key, '='))
      std::getline(subTokenStream, value);
    map[key] = value;
  }

  return true;
}

字符串转map,用于AcceptRules 规则的承认,AcceptRules(map)的函数由以下宏定义构建,map检索存在规则返回true,否则返回false

#define DEFINE_MEDIA_CHILD_FACTORY_EXTRA(REAL_PRODUCT)                         \
  bool REAL_PRODUCT##Factory::AcceptRules(                                     \
      const std::map<std::string, std::string> &map) const {                   \
    static std::list<std::string> expected_data_type_list;                     \
    static std::list<std::string> out_data_type_list;                          \
    static const char *static_keys[] = {KEY_INPUTDATATYPE, KEY_OUTPUTDATATYPE, \
                                        NULL};                                 \
    static const decltype(ExpectedInputDataType) *static_call[] = {            \
        &ExpectedInputDataType, &OutPutDataType, NULL};                        \
    static std::list<std::string> *static_list[] = {                           \
        &expected_data_type_list, &out_data_type_list, NULL};                  \
    const char **keys = static_keys;                                           \
    const decltype(ExpectedInputDataType) **call = static_call;                \
    std::list<std::string> **list = static_list;                               \
    while (*keys) {                                                            \
      auto it = map.find(*keys);                                               \
      if (it == map.end()) {                                                   \
        if ((*call)())                                                         \
          return false;                                                        \
      } else {                                                                 \
        const std::string &value = it->second;                                 \
        if (!value.empty() &&                                                  \
            !has_intersection(value.c_str(), (*call)(), *list))                \
          return false;                                                        \
      }                                                                        \
      ++keys;                                                                  \
      ++call;                                                                  \
      ++list;                                                                  \
    }                                                                          \
    return true;                                                               \
  }

以上为APP一侧flow 定义分析

#######################################cut here################################

以下rkmedia一侧flow定义

${SDK}\external\rkmedia\src\flow.cc

class FlowCoroutine;
class _API Flow {
public:
  // We may need a flow which can be sync and async.
  // This make a side effect that sync flow contains superfluous variables
  // designed for async implementation.
  Flow();
  virtual ~Flow();
  static const char *GetFlowName() { return nullptr; }
  // The GetFlowName interface is occupied by the reflector,
  // so GetFlowTag is used to distinguish Flow.
  const char *GetFlowTag() { return flow_tag.c_str(); }
  void SetFlowTag(std::string tag) { flow_tag = tag; }

  // TODO: Right now out_slot_index and in_slot_index is decided by exact
  //       subclass, automatically get these value or ignore them in future.
  bool AddDownFlow(std::shared_ptr<Flow> down, int out_slot_index,
                   int in_slot_index_of_down);
  void RemoveDownFlow(std::shared_ptr<Flow> down);

  void SendInput(std::shared_ptr<MediaBuffer> &input, int in_slot_index);
  void SetDisable() { enable = false; }

  // The Control must be called in the same thread to that create flow
  virtual int Control(unsigned long int request _UNUSED, ...) { return -1; }
  virtual int SubControl(unsigned long int request, void *arg, int size = 0) {
    SubRequest subreq = {request, size, arg};
    return Control(S_SUB_REQUEST, &subreq);
  }

  // get input size for this flow
  virtual int GetInputSize() { return 0; }

  // The global event hander is the same thread to the born thread of this
  // object.
  void RegisterEventHandler(std::shared_ptr<Flow> flow, EventHook proc);
  void UnRegisterEventHandler();
  void EventHookWait();
  void NotifyToEventHandler(EventParamPtr param, int type = MESSAGE_TYPE_FIFO);
  void NotifyToEventHandler(int id, int type = MESSAGE_TYPE_FIFO);
  MessagePtr GetEventMessage();
  EventParamPtr GetEventParam(MessagePtr msg);

  // Add Link hander For app Link
  void SetVideoHandler(LinkVideoHandler hander) {
    link_video_handler_ = hander;
  }
  LinkVideoHandler GetVideoHandler() { return link_video_handler_; }
  void SetAudioHandler(LinkAudioHandler hander) {
    link_audio_handler_ = hander;
  }
  LinkAudioHandler GetAudioHandler() { return link_audio_handler_; }
  void SetCaptureHandler(LinkCaptureHandler hander) {
    link_capture_handler_ = hander;
  }
  LinkCaptureHandler GetCaptureHandler() { return link_capture_handler_; }

  // Add hander For rtsp flow
  void SetPlayVideoHandler(PlayVideoHandler handler) {
    play_video_handler_ = handler;
  }
  PlayVideoHandler GetPlayVideoHandler() { return play_video_handler_; }
  void SetPlayAudioHandler(PlayAudioHandler handler) {
    play_audio_handler_ = handler;
  }
  PlayAudioHandler GetPlayAudioHandler() { return play_audio_handler_; }

  // Add common hander for user
  void SetUserCallBack(CallBackHandler handler, UserCallBack callback) {
    user_handler_ = handler;
    user_callback_ = callback;
  }
  void SetOutputCallBack(CallBackHandler handler, OutputCallBack callback) {
    out_handler_ = handler;
    out_callback_ = callback;
  }
  void SetEventCallBack(CallBackHandler handler, EventCallBack callback) {
    event_handler2_ = handler;
    event_callback_ = callback;
  }
  CallBackHandler GetUserHandler() { return user_handler_; }
  UserCallBack GetUserCallBack() { return user_callback_; }

  // Control the number of executions of threads inside Flow
  // _run_times: -1, Endless loop; 0, skip process; > 0, do process cnt.
  int SetRunTimes(int _run_times);
  int GetRunTimesRemaining();

  bool IsAllBuffEmpty();
  void DumpBase(std::string &dump_info);
  virtual void Dump(std::string &dump_info) { DumpBase(dump_info); }

  void StartStream();
  int GetCachedBufferNum(unsigned int &total, unsigned int &used);
  void ClearCachedBuffers();

protected:
  class FlowInputMap {
  public:
    FlowInputMap(std::shared_ptr<Flow> &f, int i) : flow(f), index_of_in(i) {}
    std::shared_ptr<Flow> flow; // weak_ptr?
    int index_of_in;
    bool operator==(const std::shared_ptr<easymedia::Flow> f) {
      return flow == f;
    }
  };
  class FlowMap {
  private:
    void SetOutputBehavior(const std::shared_ptr<MediaBuffer> &output);
    void SetOutputToQueueBehavior(const std::shared_ptr<MediaBuffer> &output);

  public:
    FlowMap() : valid(false), hold_input(HoldInputMode::NONE) {
      assert(list_mtx.valid);
    }
    FlowMap(FlowMap &&);
    void Init(Model m, HoldInputMode hold_in);
    bool valid;
    HoldInputMode hold_input;
    // down flow
    void AddFlow(std::shared_ptr<Flow> flow, int index);
    void RemoveFlow(std::shared_ptr<Flow> flow);
    std::list<FlowInputMap> flows;
    ReadWriteLockMutex list_mtx;
    std::deque<std::shared_ptr<MediaBuffer>> cached_buffers; // never drop
    std::shared_ptr<MediaBuffer> cached_buffer;
    decltype(&FlowMap::SetOutputBehavior) set_output_behavior;
  };
  class Input {
  private:
    void SyncSendInputBehavior(std::shared_ptr<MediaBuffer> &input);
    void ASyncSendInputCommonBehavior(std::shared_ptr<MediaBuffer> &input);
    void ASyncSendInputAtomicBehavior(std::shared_ptr<MediaBuffer> &input);
    // behavior when input list exceed max_cache_num
    bool ASyncFullBlockingBehavior(volatile bool &pred);
    bool ASyncFullDropFrontBehavior(volatile bool &pred);
    bool ASyncFullDropCurrentBehavior(volatile bool &pred);

  public:
    Input() : valid(false), flow(nullptr), fetch_block(true) {}
    Input(Input &&);
    void Init(Flow *f, Model m, int mcn, InputMode im, bool f_block,
              std::shared_ptr<FlowCoroutine> fc);
    bool valid;
    Flow *flow;
    Model thread_model;
    bool fetch_block;
    std::deque<std::shared_ptr<MediaBuffer>> cached_buffers;
    ConditionLockMutex mtx;
    int max_cache_num;
    InputMode mode_when_full;
    std::shared_ptr<MediaBuffer> cached_buffer;
    SpinLockMutex spin_mtx;
    decltype(&Input::SyncSendInputBehavior) send_input_behavior;
    decltype(&Input::ASyncFullBlockingBehavior) async_full_behavior;
    std::shared_ptr<FlowCoroutine> coroutine;
  };

  // Can not change the following values after initialize,
  // except AddFlow and RemoveFlow.
  int out_slot_num;
  std::vector<FlowMap> downflowmap;
  int input_slot_num;
  std::vector<Input> v_input;
  std::list<std::shared_ptr<FlowCoroutine>> coroutines;
  std::shared_ptr<ConditionLockMutex> source_start_cond_mtx;

  int down_flow_num;
  bool waite_down_flow;

  // source flow
  bool SetAsSource(const std::vector<int> &output_slots, FunctionProcess f,
                   const std::string &mark);
  bool InstallSlotMap(SlotMap &map, const std::string &mark,
                      int exp_process_time);
  bool SetOutput(const std::shared_ptr<MediaBuffer> &output,
                 int out_slot_index);
  bool ParseWrapFlowParams(const char *param,
                           std::map<std::string, std::string> &flow_params,
                           std::list<std::string> &sub_param_list);
  // As sub threads may call the variable of child class,
  // we should define this for child class when it deconstruct.
  void StopAllThread();
  bool IsEnable() { return enable; }

  template <int in_index, int out_index>
  friend bool void_transaction(Flow *f, MediaBufferVector &input_vector) {
    return f->SetOutput(input_vector[in_index], out_index);
  }
  static const FunctionProcess void_transaction00;

  CallBackHandler event_handler2_;
  EventCallBack event_callback_;

private:
  volatile bool enable;
  volatile bool quit;
  ConditionLockMutex cond_mtx;

  // event handler
  std::unique_ptr<EventHandler> event_handler_;

  friend class FlowCoroutine;

  LinkVideoHandler link_video_handler_;
  LinkAudioHandler link_audio_handler_;
  LinkCaptureHandler link_capture_handler_;

  PlayVideoHandler play_video_handler_;
  PlayAudioHandler play_audio_handler_;

  CallBackHandler user_handler_;
  UserCallBack user_callback_;

  CallBackHandler out_handler_;
  OutputCallBack out_callback_;

  // FlowTag is used to distinguish Flow.
  std::string flow_tag;

  // Control the number of executions of threads inside Flow
  int run_times;

  DEFINE_ERR_GETSET()
  DECLARE_PART_FINAL_EXPOSE_PRODUCT(Flow)
};

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值