可以使用所述管道协议打开文件描述符
我很好奇为什么有必要通过管道协议打开文件描述符?
sView 播放器通过自定义AVIOContext打开文件描述符,这是可搜索的,至少在旧测试版本的 Android 上是可搜索的。这是使用自定义 AVIOContext 打开 AVFormatContext 的伪代码。
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);
下面是提取简化的 StAVIOFileContext 类定义的尝试。
//! 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;
};