0

我已经成功为 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;
}

但这没有帮助。

有什么建议么?

谢谢

4

0 回答 0