jeudi 10 août 2017

How to get EAGAIN error from av_read_frame function in libavformat?

I can’t obtain EAGAIN error from av_read_frame function when I open context from pipe. I use boost::asio for managing connections to unix sockets and passing native socket descriptor to avformat_open_input. For correct managing i need to create kevent to get new data from socket and not to block thread until this event.

here is my example:

#include <iostream>
#include <boost/asio.hpp>
extern "C"{
#include <libavformat/avformat.h>
}

void on_accepted(std::shared_ptr<boost::asio::local::stream_protocol::socket> socket, const boost::system::error_code err){
  if(err){
      std::cout << "Error while accept " << err << std::endl;
      return;
  }
  socket->native_non_blocking(true);
  std::string path = "pipe:" + std::to_string(socket->native_handle());
  AVFormatContext* context = avformat_alloc_context();
  context->flags |= AVFMT_FLAG_NONBLOCK;
  auto open_result = avformat_open_input(&context, path.c_str(), nullptr, nullptr);
  AVPacket* packet = av_packet_alloc();
  int ret;
  while((ret = av_read_frame(context, packet)) >= 0){
      std::cout << "Packet received" << std::endl;
  }
  if(ret == EAGAIN || ret == AVERROR(EAGAIN)){
      std::cout << "EAGAIN got" << std::endl;
  }
  else{
      char buf[255];
      av_strerror( ret, buf, sizeof(buf));
      std::cout << "Error got " << buf << std::endl;
  }
  av_packet_free(&packet);
  avformat_free_context(context);
}

int main(){
  av_register_all();
  boost::asio::io_service io_service;
  ::unlink("/usr/local/sockets/test");
  boost::asio::local::stream_protocol::acceptor acceptor{io_service, "/usr/local/sockets/test"};
  acceptor.set_option(boost::asio::socket_base::reuse_address(true));
  auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>( io_service);
  acceptor.async_accept(*socket,
          std::bind(on_accepted, socket, std::placeholders::_1)
      );
  std::cout << "Start accepting" << std::endl;
  io_service.run();
}

As i see in stack trace, ffmpeg get EAGAIN error and sends read call again.

read(0x7, "\0", 0x8000)      = -1 Err#35
read(0x7, "\0", 0x8000)      = -1 Err#35
read(0x7, "\0", 0x8000)      = -1 Err#35
read(0x7, "\0", 0x8000)      = -1 Err#35
read(0x7, "\0", 0x8000)      = -1 Err#35
read(0x7, "\0", 0x8000)      = -1 Err#35

How to get EAGAIN error in my application?

Aucun commentaire:

Enregistrer un commentaire