1

I need to pass to MediaExtractor the data, for this purpose I use this method SetDataSource

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

Like this:

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;
    }
    
    ...
}

And it works fine, but now I need to work with pointer to data and data size, so I changed this method like this

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;
    }
    
    ...
}

So, I am reading the same data (as in previous ex.) in buffer also getting a size and then I open it with fmemopen and as a result getting such an error - AMEDIA_ERROR_BASE

What is a problem here? Why does it work in one case and doesn't in other in spite of it is almost the same? What am I missing?

Sirop4ik
  • 4,543
  • 2
  • 54
  • 121

1 Answers1

0

As a result, the problem turned out to be that AMediaExtractor_setDataSourceFd method accepts a file descriptor as a parameter. In order to get a file descriptor from FILE, you need to call fileno() method on FILE that was opened with fopen() then everything works well, but if the file was opened with fmemopen() then fileno() returns -1. I tried to do it through a pipe https://stackoverflow.com/a/1559018/5709159, but this approach does not work for AMediaExtractor_setDataSourceFd (I think because the pipe does not support seek()) tried to do it through a custom MediaExtractor (one of methods setDataSource()), but it was introduced only with api 29 (it does not suit me very much) in the end I did it with a workaround- I get the bytes, write to a temporary file and open this file with fopen() and call fileno() get the file descriptor and pass it to setDataSouceFd()

Sirop4ik
  • 4,543
  • 2
  • 54
  • 121