【问题标题】:AMediaExtractor gives an error in one case and doesn't in other, why?AMediaExtractor 在一种情况下会出错,而在另一种情况下不会,为什么?
【发布时间】:2020-12-16 15:02:53
【问题描述】:

我需要将数据传递给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

这里有什么问题?为什么它在一种情况下有效,而在另一种情况下却没有,尽管它几乎是一样的?我错过了什么?

【问题讨论】:

    标签: android c++ native android-mediacodec


    【解决方案1】:

    结果,问题原来是AMediaExtractor_setDataSourceFd 方法接受文件描述符作为参数。为了从FILE 获取文件描述符,您需要在FILE 上调用fileno() 方法,该方法是用fopen() 打开的,那么一切正常,但如果文件是用fmemopen() 打开的,那么fileno()返回 -1。我试图通过管道https://stackoverflow.com/a/1559018/5709159 来做到这一点,但是这种方法不适用于AMediaExtractor_setDataSourceFd(我认为是因为管道不支持seek())试图通过自定义MediaExtractor 来做到这一点(setDataSource 方法之一()),但它只在 api 29 中引入(它不太适合我)最后我用一种解决方法做到了 - 我得到字节,写入一个临时文件并用 fopen() 打开这个文件和调用fileno()获取文件描述符并传递给setDataSouceFd()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      相关资源
      最近更新 更多