AMediaExtractor 在一种情况下会出错,而在其他情况下不会,为什么?

AMediaExtractor gives an error in one case and doesn't in other, why?

我需要将数据传递给MediaExtractor,为此我使用了这个方法SetDataSource

https://developer.android.com/ndk/reference/group/media#amediaextractor_setdatasourcefd

像这样:

int32_t NDK_extractor::decode()
{
   
    FILE *fp = nullptr;
    media_status_t err;
    AMediaExtractor *ex = AMediaExtractor_new();
    fp = fopen("/storage/emulated/0/Android/data/com.test.debug/files/Models/test.mp3", "rb");


    if (fp)
    {
        err = AMediaExtractor_setDataSourceFd(ex, fileno(fp), 0, dataSize);
    }
    else
    {
        LOGE("Failed open file");
        return 0;
    }

    if (err != AMEDIA_OK)
    {
        LOGE("SOUND :: Error setting ex data source, err %d", err);
        return 0;
    }
    
    ...
}

它工作正常,但现在我需要使用指向数据和数据大小的指针,所以我像这样更改了这个方法

int32_t NDK_extractor::decode()
{

    FILE *fp = nullptr;
    media_status_t err;
    AMediaExtractor *ex = AMediaExtractor_new();
    fp = fopen("/storage/emulated/0/Android/data/com.test.debug/files/Models/test.mp3", "rb");



    fseek(fp, 0, SEEK_END);
    long lSize = ftell(fp);
    rewind(fp);
    void *buf = new unsigned char[lSize];
    fread(buf, 1, lSize, fp);
    fclose(fp);
    fp = fmemopen(buf, lSize, "r");
    
    
    
    if (fp)
    {
        err = AMediaExtractor_setDataSourceFd(ex, fileno(fp), 0, dataSize);
    }
    else
    {
        LOGE("Failed open file");
        return 0;
    }

    if (err != AMEDIA_OK)
    {
        LOGE("SOUND :: Error setting ex data source, err %d", err);
        return 0;
    }
    
    ...
}

所以,我在缓冲区中读取相同的数据(与之前的例子一样)也得到一个大小,然后我用 fmemopen 打开它,结果得到这样的错误 - AMEDIA_ERROR_BASE

这里有什么问题?为什么它在一种情况下有效而在其他情况下却不起作用,尽管它几乎相同?我错过了什么?

结果,问题原来是AMediaExtractor_setDataSourceFd方法接受一个文件描述符作为参数。为了从 FILE 获取文件描述符,您需要在使用 fopen() 打开的 FILE 上调用 fileno() 方法然后一切正常,但是如果文件被打开使用 fmemopen() 然后 fileno() returns -1。我试图通过管道 来完成,但这种方法不适用于 AMediaExtractor_setDataSourceFd(我认为是因为管道不支持 seek())试图通过自定义 MediaExtractor (方法 setDataSource() 之一),但它仅通过 api 29 引入(它不太适合我)最后我用一种解决方法做到了 - 我得到字节,写入临时文件并使用 fopen() 打开此文件并调用 fileno() 获取文件描述符并将其传递给 setDataSouceFd()