Почему MediaExtractor делает ошибку AMEDIA_ERROR_BASE в одном случае и не делает в другом?
Мне нужно передать 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;
}
...
}
И это работает, но мне нужно работать с поинтером на дату (void*) и ее размером (data_size) для этого я пробую прочитать тот же файл получить поинтер и размер и уже работать с этим. Вот так
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 и так же передаю его в метод setDataSource и получаю ошибку AMEDIA_ERROR_BASE
То есть вроде все тоже самое, но что то не так, что то я упускаю тут.
Что не так?
Ответы (1 шт):
В итоге проблема оказалась в том, что этот метод принимает файл дескриптор как параметр для того, что получить файл дескриптор с FILE нужно вызвать вот этот метод fileno() и вот как оказалось, что если вызывать этот метод на файле который был открыт через fopen() то все работает, но если файл был открыт через fmemopen() то fileno() возвращает -1. Я пробовал сделать это через pipe https://stackoverflow.com/a/1559018/5709159 , но этот подход не работает для AMediaExtractor_setDataSourceFd (я думаю потому, что pipe не поддерживает seek()) пробовал сделать через кастомный MediaExtractor (один из методов setDataSource()) , но он был введен только с api 29 (мне это не сильно подходит) в итоге сделал с костылем - получаем байты пишем во временный файл и уже открываем этот файл через fopen() и вызываем fileno() получаем файл дескриптор и передаем в setDataSouceFd()