-
-
Save kostyll/69a83dcca980a3595d15 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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