瑞芯微rv1126 SDK代码基础分析---Flow::StartStream()分析(2)

以下文章用于记录个人学习使用,如有出入请帮忙指正,不胜感激!

承接上编博文分析:https://blog.csdn.net/zhfabel/article/details/119184807

上篇文章分析到:

void SourceStreamFlow::ReadThreadRun() {
  prctl(PR_SET_NAME, this->tag.c_str());
  source_start_cond_mtx->lock();
  if (waite_down_flow) {
    if (down_flow_num == 0 && IsEnable()) {
      source_start_cond_mtx->wait();
    }
  }
  source_start_cond_mtx->unlock();
  while (loop) {
    if (stream->Eof()) {
      // TODO: tell that I reach eof
      SetDisable();
      break;
    }
    auto buffer = stream->Read();
    SendInput(buffer, 0);
  }
}

SourceStreamFlow::ReadThreadRun()中的SendInput(buffer, 0)函数,主要与flow类相关,本篇主要以auto buffer = stream->Read();为主线进一步分析stream的类概论。

手册Rockchip_Instructions_Linux_MediaServer_CN 中定义:Stream表示FLow使用的处理方法。

先看下,stream对象的定义处:$(SDK)\external\rkmedia\src\flow\source_stream_flow.cc

class SourceStreamFlow : public Flow {
public:
  SourceStreamFlow(const char *param);
  virtual ~SourceStreamFlow();
  static const char *GetFlowName() { return "source_stream"; }
  virtual int Control(unsigned long int request, ...) final {
    if (!stream)
      return -1;
    va_list vl;
    va_start(vl, request);
    void *arg = va_arg(vl, void *);
    va_end(vl);
    return stream->IoCtrl(request, arg);
  }

private:
  void ReadThreadRun();
  bool loop;
  std::thread *read_thread;
  std::shared_ptr<Stream> stream;
  std::string tag;
};

 std::shared_ptr<Stream> stream这句指引我们到:$(SDK)\external\rkmedia\include\easymedia\stream.h,stream类接口定义不大,直接贴出

// interface
class _API Stream {
public:
  static StreamOperation c_operations;

  Stream() : readable(false), writeable(false), seekable(false) {}
  virtual ~Stream() = default;

  virtual size_t Read(void *ptr, size_t size, size_t nmemb) = 0;
  virtual size_t Write(const void *ptr, size_t size, size_t nmemb) = 0;
  // whence: SEEK_SET, SEEK_CUR, SEEK_END
  virtual int Seek(int64_t offset, int whence) = 0;
  virtual long Tell() = 0;

  virtual int NewStream(std::string new_path _UNUSED) { return -1; };
  virtual size_t WriteAndClose(const void *ptr  _UNUSED,
                    size_t size  _UNUSED, size_t nmemb _UNUSED) { return -1; };
  virtual int ReName(std::string old_path _UNUSED,
                       std::string new_path _UNUSED) { return -1; };

  virtual bool Readable() { return readable; }
  virtual bool Writeable() { return writeable; }
  virtual bool Seekable() { return seekable; }

  void SetReadable(bool able) { readable = able; }
  void SetWriteable(bool able) { writeable = able; }
  void SetSeekable(bool able) { seekable = able; }

  virtual bool Eof() { return false; }

  // No need size input. For some device, such as V4L2, always return specific
  // buffer
  virtual std::shared_ptr<MediaBuffer> Read() { return nullptr; }
  virtual bool Write(std::shared_ptr<MediaBuffer>) { return false; }
  // The IoCtrl must be called in the same thread of Read()/Write()
  virtual int IoCtrl(unsigned long int request _UNUSED, ...) { return -1; }
  virtual int SubIoCtrl(unsigned long int request _UNUSED, void *arg, int size = 0) {
    SubRequest subreq = {request, size, arg};
    return IoCtrl(S_SUB_REQUEST, &subreq);
  }

  // read data as image by ImageInfo
  bool ReadImage(void *ptr, const ImageInfo &info);

protected:
  virtual int Open() = 0;
  virtual int Close() = 0;

  friend int local_close(void *stream);

private:
  bool readable;
  bool writeable;
  bool seekable;

  DECLARE_PART_FINAL_EXPOSE_PRODUCT(Stream)
};

从仅3个成员变量看出,定义了stream的可读,可写,可seek。其中除以下4个函数外其他都是虚函数,在实际继承类中定义具体的功能。

  void SetReadable(bool able) { readable = able; }

  void SetWriteable(bool able) { writeable = able; }

  void SetSeekable(bool able) { seekable = able; }

  // read data as image by ImageInfo

  bool ReadImage(void *ptr, const ImageInfo &info);

SourceStreamFlow::SourceStreamFlow(const char *param)的构造函数中有如下stream是实例化:stream = REFLECTOR(Stream)::Create<Stream>(stream_name, stream_param.c_str());

以第一篇分析的实例化一个对象指针。

代码位置:$(SDK\external\rkmedia\include\easymedia\reflector.h

以Read()函数为主线,跟踪分析下继承Stream基类的具体实现:class V4L2Stream的继承类分析,位置:$(SDK)\external\rkmedia\src\stream\camera\v4l2_stream.h;其中Read仍是虚函数,未具体实现,class V4L2Stream进一步被class V4L2CaptureStream,所以分析 V4L2CaptureStream::Read()函数。

  virtual size_t Read(void *ptr _UNUSED, size_t size _UNUSED,
                      size_t nmemb _UNUSED) final {
    return 0;
  }
std::shared_ptr<MediaBuffer> V4L2CaptureStream::Read() {
  const char *dev = device.c_str();
  if (!started && v4l2_ctx->SetStarted(true))
    started = true;

  struct v4l2_buffer buf;
  memset(&buf, 0, sizeof(buf));
  buf.type = capture_type;
  buf.memory = memory_type;
  int ret = v4l2_ctx->IoCtrl(VIDIOC_DQBUF, &buf);
  if (ret < 0) {
    LOG("%s, ioctl(VIDIOC_DQBUF): %m\n", dev);
    return nullptr;
  }
  struct timeval buf_ts = buf.timestamp;
  MediaBuffer &mb = buffer_vec[buf.index];
  std::shared_ptr<MediaBuffer> ret_buf;
  if (buf.bytesused > 0) {
    if (pix_fmt != PIX_FMT_NONE) {
      ImageInfo info{pix_fmt, width, height, width, height};
      ret_buf = std::make_shared<AutoQBUFImageBuffer>(mb, info, v4l2_ctx, buf);
    } else {
      ret_buf = std::make_shared<AutoQBUFMediaBuffer>(mb, v4l2_ctx, buf);
    }
  }
  if (ret_buf) {
    assert(ret_buf->GetFD() == mb.GetFD());
    if (buf.memory == V4L2_MEMORY_DMABUF) {
      assert(ret_buf->GetFD() == buf.m.fd);
    }
    ret_buf->SetAtomicTimeVal(buf_ts);
    ret_buf->SetTimeVal(buf_ts);
    ret_buf->SetValidSize(buf.bytesused);
  } else {
    if (v4l2_ctx->IoCtrl(VIDIOC_QBUF, &buf) < 0)
      LOG("%s, index=%d, ioctl(VIDIOC_QBUF): %m\n", dev, buf.index);
  }

  return ret_buf;
}

总体看函数返回值为std::shared_ptr<MediaBuffer>,应该是读到的camera数据流,返回数据流的缓存块,使用v4l2的架构接口(如下代码段可以看出)。

  if (ret_buf) {
    assert(ret_buf->GetFD() == mb.GetFD());
    if (buf.memory == V4L2_MEMORY_DMABUF) {
      assert(ret_buf->GetFD() == buf.m.fd);
    }
    ret_buf->SetAtomicTimeVal(buf_ts);
    ret_buf->SetTimeVal(buf_ts);
    ret_buf->SetValidSize(buf.bytesused);
  } else {
    if (v4l2_ctx->IoCtrl(VIDIOC_QBUF, &buf) < 0)
      LOG("%s, index=%d, ioctl(VIDIOC_QBUF): %m\n", dev, buf.index);
  }

综上分析,最终read就是调用了通过linux v4l2架构或则Media Controller
架构获取到camera的数据流缓存

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值