Last active
June 24, 2022 18:12
-
-
Save xlphs/9895065 to your computer and use it in GitHub Desktop.
MyIOContext
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 = 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
Hello Marika, great job with this sample. Saved me a lot of time figuring out the interface for the callback functions.
If I may suggest an improvement, consider following changes:
line 49:
line 90:
Setting the padding to 1 instead of the defined value in the library can cause invalid read outside of the buffer, which leads to segfault.
And apparently not setting the mime_type can cause trouble as well. Empty string should work fine, as avformat tries to match it against its known types, before using it.
Source:
https://ffmpeg.org/doxygen/2.8/structAVProbeData.html#a814cca49dda3f578ebb32d4b2f74368a
Cheers!