it is possible to open the file descriptor using the pipe protocol as described
I'm curious why it is necessary opening file descriptor via pipe protocol?
sView player opens file descriptor by custom AVIOContext, which is seekable, at least on older tested versions of Android. Here is a pseudo-code opening AVFormatContext with custom AVIOContext.
int aFileDescriptor = myResMgr->openFileDescriptor(theFileToLoad);
AVFormatContext* aFormatCtx = avformat_alloc_context();
StAVIOContext myAvioContext;
if(!myAvioContext.openFromDescriptor(aFileDescriptor, "rb")) {
// error
}
aFormatCtx->pb = myAvioContext.getAvioContext();
int avErrCode = avformat_open_input(&aFormatCtx, theFileToLoad, NULL, NULL);
Below is an attempt to extract a simplified StAVIOFileContext class definition.
//! Wrapper over AVIOContext for passing the custom I/O.
class StAVIOContext {
public:
//! Main constructor.
StAVIOContext() {
const int aBufferSize = 32768;
unsigned char* aBufferIO = (unsigned char* )av_malloc(aBufferSize + AV_INPUT_BUFFER_PADDING_SIZE);
AVIOContext* myAvioCtx = avio_alloc_context (aBufferIO, aBufferSize, 0, this, readCallback, writeCallback, seekCallback);
}
//! Destructor.
virtual ~StAVIOContext() {
close();
if (myAvioCtx != NULL) { av_free (myAvioCtx); }
}
//! Close the file.
void close() {
if(myFile != NULL) {
fclose(myFile);
myFile = NULL;
}
}
//! Associate a stream with a file that was previously opened for low-level I/O.
//! The associated file will be automatically closed on destruction.
bool openFromDescriptor(int theFD, const char* theMode) {
close();
#ifdef _WIN32
myFile = ::_fdopen(theFD, theMode);
#else
myFile = ::fdopen(theFD, theMode);
#endif
return myFile != NULL;
}
//! Access AVIO context.
AVIOContext* getAvioContext() const { return myAvioCtx; }
public:
//! Virtual method for reading the data.
virtual int read (uint8_t* theBuf,
int theBufSize) {
if(myFile == NULL) { return -1; }
int aNbRead = (int )::fread(theBuf, 1, theBufSize, myFile);
if(aNbRead == 0 && feof(myFile) != 0) { return AVERROR_EOF; }
return aNbRead;
}
//! Virtual method for writing the data.
virtual int write (uint8_t* theBuf,
int theBufSize) {
if(myFile == NULL) { return -1; }
return (int )::fwrite(theBuf, 1, theBufSize, myFile);
}
//! Virtual method for seeking to new position.
virtual int64_t seek (int64_t theOffset,
int theWhence) {
if(theWhence == AVSEEK_SIZE || myFile == NULL) { return -1; }
#ifdef _WIN32
bool isOk = ::_fseeki64(myFile, theOffset, theWhence) == 0;
#else
bool isOk = ::fseeko(myFile, theOffset, theWhence) == 0;
#endif
if(!isOk) { return -1; }
#ifdef _WIN32
return ::_ftelli64(myFile);
#else
return ::ftello(myFile);
#endif
}
private:
//! Callback for reading the data.
static int readCallback(void* theOpaque,
uint8_t* theBuf,
int theBufSize) {
return theOpaque != NULL
? ((StAVIOContext* )theOpaque)->read(theBuf, theBufSize)
: 0;
}
//! Callback for writing the data.
static int writeCallback(void* theOpaque,
uint8_t* theBuf,
int theBufSize) {
return theOpaque != NULL
? ((StAVIOContext* )theOpaque)->write(theBuf, theBufSize)
: 0;
}
//! Callback for seeking to new position.
static int64_t seekCallback(void* theOpaque,
int64_t theOffset,
int theWhence) {
return theOpaque != NULL
? ((StAVIOContext* )theOpaque)->seek(theOffset, theWhence)
: -1;
}
protected:
AVIOContext* myAvioCtx;
FILE* myFile;
};