Android用のffmpegを正常にコンパイルしました。mp4 ファイルを開くだけの簡単なアプリケーションを作成しました。
int main(int argc, char * argv[])
{
av_register_all();
__android_log_write(ANDROID_LOG_INFO, "NDK", "Opening file: /sdcard/test.mp4...");
if (avformat_open_input(&pFormatCtx, "/sdcard/test.mp4", NULL, NULL) != 0) {
__android_log_write(ANDROID_LOG_INFO, "NDK", "file not opened\n");
return -1;
}
__android_log_write(ANDROID_LOG_INFO, "NDK", "file opened\n");
}
このコードを実行すると、C コードがここでクラッシュします。
06-06 18:22:42.629: I/DEBUG(31): #00 pc 00159804 /data/data libffmpeg.so
06-06 18:22:42.629: I/DEBUG(31): #01 lr 809465dc /data/data libffmpeg.so
ndk スタック書き込み:
Stack frame #00 pc 00159804 /data/data/.../lib/libffmpeg.so: Routine av_opt_set_dict in libavutil/opt.c:552
av_opt_set_dict 関数は次のとおりです。
int av_opt_set_dict(void *obj, AVDictionary **options)
{
AVDictionaryEntry *t = NULL;
AVDictionary *tmp = NULL;
int ret = 0;
while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
ret = av_set_string3(obj, t->key, t->value, 1, NULL);
if (ret == AVERROR_OPTION_NOT_FOUND)
av_dict_set(&tmp, t->key, t->value, 0);
else if (ret < 0) {
av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
break;
}
ret = 0;
}
av_dict_free(options);
*options = tmp;
return ret;
}
552行は次のとおりです。
while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
このコードは私のLinuxマシンで動作します(もちろん、Linuxの場合は.so、Androidの場合はndkビルドの.soファイルを使用します)が、Androidの下では機能しません。
また、ルート化された HTC Desire Z では動作しますが、エミュレーターやルート化されていないデバイスでは動作しません。
ここで、libavformat/file.c file_check 関数を変更する必要があるという投稿を見つけました。
static int file_check(URLContext *h, int mask)
{
struct stat st;
int ret = stat(h->filename, &st);
if (ret < 0)
return AVERROR(errno);
ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ : 0;
ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
return ret;
}
に
static int file_check(URLContext *h, int mask)
{
struct stat st;
int ret = stat(h->filename, &st);
if (ret < 0)
return AVERROR(errno);
ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ : 0;
ret |= st.st_mode&S_IRGRP ? mask&AVIO_FLAG_READ : 0;
ret |= st.st_mode&S_IROTH ? mask&AVIO_FLAG_READ : 0;
ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
ret |= st.st_mode&S_IWGRP ? mask&AVIO_FLAG_WRITE : 0;
ret |= st.st_mode&S_IWOTH ? mask&AVIO_FLAG_WRITE : 0;
return ret;
}
しかし、それは助けにはなりませんでした。
助言がありますか?
ありがとう