MyIOContext
#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 = 4096; | |
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); | |
av_free(buffer); | |
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