How do I use AVIOContext for custom IO?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How do I use AVIOContext for custom IO?

wl2776
Administrator
I've downloaded precompiled win32 binaries of FFmpeg and dev files from http://ffmpeg.zeranoe.com/builds/ (version git-9c2651a from 2011-07-23) and have found that my usual approach to have LibAV read from my custom input stream doesn't work.

I was applying the scheme that I was using with ByteIOContext for years.
No ByteIOContext it deprecated, and I've switched to AVIOContext.

I have defined a class from custom IO (currently, for the research purposes, it anyway reads from file using read(), but I'm going to have a network input from custom protocol), allocated AVIOcontext and tried to call av_open_input_stream.
av_open_input_stream always returns -1 and doesn't call reading methods from my class.

Here is my code. It's rather simple.

So, what has changed in libav and how should I change my code?

class FileReader { 
protected:
  int fd;
public:
FileReader(const char *filename, int buf_size){
  fd = _open(filename, _O_BINARY| _O_RDONLY);
};

~FileReader() {
 _close(fd);
};

int read(uint8_t *buf, int buf_size){
  int len = _read(fd, buf, buf_size);
  return len;
};

};

#define bsize 30000

int read_packet(void *opaque, uint8_t *buf, int buf_size)
{
  FileReader *rdr = (FileReader *)opaque;
  return rdr->read(buf, buf_size);
}

int main(void) {

  AVFormatContext *fc;
  AVIOContext *pb;
  AVFormatParameters ap;
  AVInputFormat *iformat;

  unsigned char *buffer = (unsigned char *)av_malloc(bsize);
  const char *filename = "C:\\wl\\clrc\\Debug\\464216.wav";
  FileReader* fr = new FileReader(filename, bsize);

  int r;

  av_register_all();
  av_log_set_level(AV_LOG_DEBUG);
  
  pb = avio_alloc_context(buffer, bsize, 1, fr, read_packet, NULL, NULL);
  pb->seekable = 0;
  pb->write_flag = 0;
  
  iformat = av_find_input_format("wav");

  memset(&ap, 0, sizeof(ap));
  ap.prealloced_context = 1;

  r = av_open_input_stream(&fc, pb, "", iformat, NULL);

  if(r < 0)
    goto beach;
  
  r = av_find_stream_info(fc);
  dump_format(fc, 0, filename, 0);
  av_close_input_file(fc);

beach:
  av_free(buffer);
  av_free(pb);
  return 0;
}
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How do I use AVIOContext for custom IO?

wl2776
Administrator
wl2776 wrote
I was applying the scheme that I was using with ByteIOContext for years.
Now ByteIOContext it deprecated, and I've switched to AVIOContext.
...
Here is my code. It's rather simple.
So, what has changed in libav and how should I change my code?
It seems, I've found the solution :(
If I link my app with the dynamic libraries, it doesn't work. My function read_packets isn't called.
If I link my app with static libraries, my function is called.

I've met something similar, when worker with the GStreamer and tried to define a custom callbacks instead of the default one.
There was an API function which was passed a single argument - the address of the callback function.
This function was to remove that callback from the internal list.
And the default callback function had different addresses when seen from DLL, and when seen from an application.

Sad, will have to store two copies of code in two components. Damned Microsoft. :(
Loading...