ChinaFFmpeg

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 9407|回复: 0

[Android] 使用libx264编码找不到编码器问题,这个问题卡主我好久了

[复制链接]
发表于 2019-9-29 13:49:12 | 显示全部楼层 |阅读模式
背景:
本人新手,目前在尝试Android平台使用ffmpeg进行h264编码。我已经把ffmpeg编译成动态库并能够使用jni调用一些解码之类的操作。
但是今天想要进行h264编码操作却一直提示找不到编码器。我运行的是ffmpeg自带的例子encode_video.c。我将它稍微改造了一下输入输出,使用jni调用。
问题:
从打印的log来看,问题出codec = avcodec_find_encoder_by_name("libx264");一直返回NULL。
而如果我改成 avcodec_find_encoder(AV_CODEC_ID_H264),这个方法倒是不报错了,但是接下来的ret = avcodec_open2(c, codec, NULL);却会返回错误permission denied。

下面附带我编译x264、ffmpeg的脚本,以及相关代码:
我用来编译x264的脚本:
[Bash shell] 纯文本查看 复制代码
#!/bin/bash
NDK=/Users/路径打码了/Library/Android/sdk/ndk-bundle
API=17
PLATFORM=arm-linux-androideabi
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
SYSROOT=$NDK/platforms/android-$API/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
CPU=arm
PREFIX=$(pwd)/x264-lib

build_one()
{
./configure \
--prefix=$PREFIX \
--enable-static \
--enable-pic \
--disable-asm \
--disable-cli \
--host=arm-linux \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--extra-cflags="-I$ASM -isysroot $ISYSROOT" \
--extra-ldflags="-marm" \
--sysroot=$SYSROOT
}
build_one
make clean
make -j4
make install




下面是编译ffmpeg动态链接库的脚本:
[Bash shell] 纯文本查看 复制代码
#!/bin/bash
NDK=/Users/路径打码/Library/Android/sdk/ndk-bundle
API=17
PLATFORM=arm-linux-androideabi
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
SYSROOT=$NDK/platforms/android-$API/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
CPU=arm
PREFIX=$(pwd)/android/$CPU
H264=/Users/wangpeng55/ffmpeg/x264/x264-lib

build_one()
{
./configure \
--prefix=$PREFIX \
--target-os=android \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--disable-stripping \
--enable-gpl --enable-shared --disable-static --enable-nonfree --enable-version3 --enable-small --disable-vda --disable-iconv \
--disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=libfaac \
--disable-muxers --enable-muxer=mov --enable-muxer=ipod --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi \
--disable-decoders --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 \
--disable-demuxers --enable-demuxer=h264 --enable-demuxer=avi --enable-demuxer=mpc --enable-demuxer=mov \
--disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 \
--disable-protocols --enable-protocol=file \
--disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb \
--disable-indevs --enable-zlib \
--disable-outdevs --disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug \
--arch=arm \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
--sysroot=$SYSROOT \
--extra-cflags="-I$H264/include -isysroot $ISYSROOT -D__ANDROID_API__=$API -U_FILE_OFFSET_BITS -Os -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm" \
--extra-ldflags="-L$H264/lib"
$ADDITIONAL_CONFIGURE_FLAG
}
build_one
make clean
make -j4
make install



以上编译都能够成功编译。

接下来是进行编码的代码:
[C] 纯文本查看 复制代码
    const char *filename, *codec_name;
    const AVCodec *codec;
    AVCodecContext *c = NULL;
    int i, ret, x, y;
    FILE *f;
    AVFrame *frame;
    AVPacket *pkt;
    uint8_t endcode[] = {0, 0, 1, 0xb7};

    filename = "/storage/emulated/0/output.h264";
    codec_name = "libx264";

    av_register_all();
    /* find the mpeg1video encoder */
    codec = avcodec_find_encoder_by_name(codec_name);     // 1、此处获取h264编码器总为Null
    if (!codec) {
        LOGE("Codec id %d not found\n", AV_CODEC_ID_H264);
        return -1;
    }

    c = avcodec_alloc_context3(codec);
    if (!c) {
        LOGE("Could not allocate video codec context\n");
        return -1;
    }

    pkt = av_packet_alloc();
    if (!pkt)
        return -1;

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */
    c->time_base = (AVRational) {1, 25};
    c->framerate = (AVRational) {25, 1};

    /* emit one intra frame every ten frames
     * check frame pict_type before passing frame
     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
     * then gop_size is ignored and the output of encoder
     * will always be I frame irrespective to gop_size
     */
    c->gop_size = 10;
    c->max_b_frames = 1;
    c->pix_fmt = AV_PIX_FMT_YUV420P;

    if (codec->id == AV_CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);

    /* open it */
    ret = avcodec_open2(c, codec, NULL);      // 2、如果使AV_CODEC_ID_H264获取编码器,这个地方又会报错
    if (ret < 0) {
        LOGE("Could not open codec: %s\n", av_err2str(ret));
        return -1;
    }

    f = fopen(filename, "wb");
    if (!f) {
        LOGE("Could not open %s\n", filename);
        return -1;
    }

    frame = av_frame_alloc();
    if (!frame) {
        LOGE("Could not allocate video frame\n");
        return -1;
    }
    frame->format = c->pix_fmt;
    frame->width = c->width;
    frame->height = c->height;

    ret = av_frame_get_buffer(frame, 32);
    if (ret < 0) {
        LOGE("Could not allocate the video frame data\n");
        return -1;
    }

    /* encode 1 second of video */
    for (i = 0; i < 25; i++) {
        fflush(stdout);

        /* make sure the frame data is writable */
        ret = av_frame_make_writable(frame);
        if (ret < 0)
            exit(1);

        /* prepare a dummy image */
        /* Y */
        for (y = 0; y < c->height; y++) {
            for (x = 0; x < c->width; x++) {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }

        /* Cb and Cr */
        for (y = 0; y < c->height / 2; y++) {
            for (x = 0; x < c->width / 2; x++) {
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }

        frame->pts = i;

        /* encode the image */
        encode(c, frame, pkt, f);
    }

    /* flush the encoder */
    encode(c, NULL, pkt, f);

    /* add sequence end code to have a real MPEG file */
    fwrite(endcode, 1, sizeof(endcode), f);
    fclose(f);

    avcodec_free_context(&c);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    LOGI("encode 2 finished");

    return 0;



这个问题已经卡主我三天了。。。google都翻遍了,ffmpeg用了3.4.2和4.0.4两个版本都不行。一直不知道问题出在哪里,大概猜测试因为ffmpeg没有将lib264编译进so库?但是我要怎么检查我编译好的ffmpeg的动态链接库包含了lib264这样的第三方的类库呢??
请求大神帮忙,先谢谢了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|Archiver|ChinaFFmpeg

GMT+8, 2024-12-27 05:46 , Processed in 0.066516 second(s), 16 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表