Skip to content

Instantly share code, notes, and snippets.

@kostyll
Forked from xlphs/MyIOContext.cpp
Last active August 29, 2015 14:23
Show Gist options
  • Save kostyll/69a83dcca980a3595d15 to your computer and use it in GitHub Desktop.
Save kostyll/69a83dcca980a3595d15 to your computer and use it in GitHub Desktop.
#include <cstdio>
#include <string>
class MyIOContext {
public:
std::string datafile;
AVIOContext *ioCtx;
uint8_t *buffer; // internal buffer for ffmpeg
int bufferSize;
FILE *fh;
public:
MyIOContext(const std::string &datafile);
~MyIOContext();
void initAVFormatContext(AVFormatContext *);
};
static int IOReadFunc(void *data, uint8_t *buf, int buf_size) {
MyIOContext *hctx = (MyIOContext*)data;
size_t len = fread(buf, 1, buf_size, hctx->fh);
if (len == 0) {
// Let FFmpeg know that we have reached EOF, or do something else
return AVERROR_EOF;
}
return (int)len;
}
// whence: SEEK_SET, SEEK_CUR, SEEK_END (like fseek) and AVSEEK_SIZE
static int64_t IOSeekFunc(void *data, int64_t pos, int whence) {
if (whence == AVSEEK_SIZE) {
// return the file size if you wish to
}
MyIOContext *hctx = (MyIOContext*)data;
int rs = fseek(hctx->fh, (long)pos, whence);
if (rs != 0) {
return -1;
}
long fpos = ftell(hctx->fh); // int64_t is usually long long
return (int64_t)fpos;
}
MyIOContext::MyIOContext(const std::string &s) {
datafile.assign(s);
// allocate buffer
bufferSize = 102400; // FIXME: not sure what size to use
buffer = (uint8_t *)av_malloc(bufferSize); // see destructor for details
// open file
fh = fopen(datafile.c_str(), "rb");
if (!fh) {
fprintf(stderr, "MyIOContext: failed to open file %s\n",
datafile.c_str());
}
// allocate the AVIOContext
ioCtx = avio_alloc_context(
buffer, bufferSize, // internal buffer and its size
0, // write flag (1=true,0=false)
(void*)this, // user data, will be passed to our callback functions
IOReadFunc,
0, // no writing
IOSeekFunc
);
}
MyIOContext::~MyIOContext() {
if (fh) fclose(fh);
// NOTE: ffmpeg messes up the buffer
// so free the buffer first then free the context
av_free(ioCtx->buffer);
ioCtx->buffer = NULL;
av_free(ioCtx);
}
void MyIOContext::initAVFormatContext(AVFormatContext *pCtx) {
pCtx->pb = ioCtx;
pCtx->flags |= AVFMT_FLAG_CUSTOM_IO;
// you can specify a format directly
//pCtx->iformat = av_find_input_format("h264");
// or read some of the file and let ffmpeg do the guessing
size_t len = fread(buffer, 1, bufferSize, fh);
if (len == 0) return;
fseek(fh, 0, SEEK_SET); // reset to beginning of file
AVProbeData probeData;
probeData.buf = buffer;
probeData.buf_size = bufferSize - 1;
probeData.filename = "";
pCtx->iformat = av_probe_input_format(&probeData, 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment