2

我在 android 上使用 FFmpeg 来解码 mp3。我在配置时设置了所有解码器启用并正确制作了 .so 文件。这是为配置文件添加参数的 .sh:

NDK=~/android-ndk-r5b
PLATFORM=$NDK/platforms/android-8/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86


function build_one
{
./configure --target-os=linux \
    --prefix=$PREFIX \
    --enable-cross-compile \
    --extra-libs="-lgcc" \
    --arch=arm \
    --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
    --nm=$PREBUILT/bin/arm-linux-androideabi-nm \
    --sysroot=$PLATFORM \
    --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums  -fno-strict-aliasing -finline-limit=300 $OPTIMIZE_CFLAGS " \
    --disable-shared \
    --enable-static \
    --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -nostdlib -lc -lm -ldl -llog" \
    --enable-demuxer=mov \
    --enable-demuxer=h264 \
    --disable-ffplay \
    --enable-protocol=file \
    --enable-avformat \
    --enable-avcodec \
    --enable-decoder=rawvideo \
    --enable-decoder=mjpeg \
    --enable-decoder=h263 \
    --enable-decoder=mpeg4 \
    --enable-decoder=h264 \
    --enable-decoder=mp3 \
    --enable-decoder=mp3adu \
    --enable-decoder=mp3adufloat \
    --enable-decoder=mp3float \
    --enable-decoder=mp3on4 \
    --enable-decoder=mp3on4float \
    --enable-parser=h264 \
    --disable-network \
    --enable-zlib \
    --disable-avfilter \
    --disable-avdevice \
    $ADDITIONAL_CONFIGURE_FLAG


make clean
make  -j4 install

$PREBUILT/bin/arm-linux-androideabi-ar d libavcodec/libavcodec.a inverse.o

$PREBUILT/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -soname libffmpeg.so -shared -nostdlib  -z,noexecstack -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a -lc -lm -lz -ldl -llog  --warn-once  --dynamic-linker=/system/bin/linker $PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a
}

#arm v7vfpv3
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU "
PREFIX=./android/$CPU 
ADDITIONAL_CONFIGURE_FLAG=
build_one

我可以读取文件并获取信息(解码类型\格式类型),然后按照FFmpeg的示例调用avcodec_decode_audio3来解码音频文件,它返回-1,解码失败。有人能告诉我发生了什么吗,谢谢!

#include <stdlib.h>
#include <stdio.h>
#include <jni.h>
#include <android/log.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"

#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
#define LOG_TAG "FFmpegTest"
#define LOG_LEVEL 10
#define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
#define LOGE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}

char *sourceFileName;
char *resultFileName;
AVFormatContext *gFormatCtx;
int audioStreamIndex;
AVCodec *gCodec;
AVCodecContext *gCodecCtx;
FILE *sourceFile, *resultFile;
int out_size, len;
uint8_t *outbuf;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;

JNIEXPORT void JNICALL Java_roman10_ffmpegTest_VideoBrowser_naDecode(JNIEnv *pEnv, jobject pObj, jstring source_file_name, jstring result_file_name)
{
    LOGI(10, "start decode.");
    /* get source file's name */
    sourceFileName = (char *)(*pEnv)->GetStringUTFChars(pEnv, source_file_name, NULL);
    if (sourceFileName == NULL) {
        LOGE(1, "cannot get the source file name!");
        exit(1);
    }
    LOGI(10, "source file name is %s", sourceFileName);

    avcodec_init();

    av_register_all();

    /* get format somthing of source file to AVFormatContext */
    int lError;
    if ((lError = av_open_input_file(&gFormatCtx, sourceFileName, NULL, 0, NULL)) !=0 ) {
        LOGE(1, "Error open source file: %d", lError);
        exit(1);
    }
    if ((lError = av_find_stream_info(gFormatCtx)) < 0) {
        LOGE(1, "Error find stream information: %d", lError);
        exit(1);
    }
    LOGI(10, "audio format: %s", gFormatCtx->iformat->name);
    LOGI(10, "audio bitrate: %d", gFormatCtx->bit_rate);

    /* ???get audio stream's id and codec of source file??? */
    audioStreamIndex = av_find_best_stream(gFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &gCodec, 0);
    LOGI(10, "audioStreamIndex %d", audioStreamIndex);
    if (audioStreamIndex == AVERROR_STREAM_NOT_FOUND) {
        LOGE(1, "cannot find a audio stream");
        exit(1);
    } else if (audioStreamIndex == AVERROR_DECODER_NOT_FOUND) {
        LOGE(1, "audio stream found, but no decoder is found!");
        exit(1);
    }
    LOGI(10, "audio codec: %s", gCodec->name);

    /* get codec somthing of audio stream to AVCodecContext */
    gCodecCtx = gFormatCtx->streams[audioStreamIndex]->codec;
    if (avcodec_open(gCodecCtx, gCodec) < 0) {
    LOGE(1, "cannot open the audio codec!");
        exit(1);
    }

    /* ???gCodec = avcodec_find_decoder(gCodecCtx->codec_id);
    if (!gCodec) {
    LOGE(1, "codec not found");
        return;
    }

    gCodecCtx= avcodec_alloc_context();

    if (avcodec_open(gCodecCtx, gCodec) < 0) {
    LOGE(1, "could not open codec");
        exit(1);
    }??? */

    outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

    sourceFile = fopen(sourceFileName, "rb");
    if (!sourceFile) {
    LOGE(1, "could not open %s", sourceFileName);
        exit(1);
    }
    /* get result file's name */
    resultFileName = (char *)(*pEnv)->GetStringUTFChars(pEnv, result_file_name, NULL);
    LOGI(10, "result file name is %s", resultFileName);
    resultFile = fopen(resultFileName, "wb");
    if (!resultFile) {
    LOGE(1, "could not create result file");
        av_free(gCodecCtx);
        exit(1);
    }

    av_init_packet(&avpkt);

    avpkt.data = inbuf;
    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, sourceFile);
    LOGI(10, "avpkt.size: %d", avpkt.size);
    /* decode file */
    while (avpkt.size > 0) {
        out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
        len = avcodec_decode_audio3(gCodecCtx, (short *)outbuf, &out_size, &avpkt);
        if (len < 0) {
            LOGE(1, "Error while decoding: %d", len);
            exit(1);
        }
        if (out_size > 0) {
            fwrite(outbuf, 1, out_size, resultFile);
        }
        avpkt.size -= len;
        avpkt.data += len;
        if (avpkt.size < AUDIO_REFILL_THRESH) {
            memmove(inbuf, avpkt.data, avpkt.size);
            avpkt.data = inbuf;
            len = fread(avpkt.data + avpkt.size, 1,
                        AUDIO_INBUF_SIZE - avpkt.size, sourceFile);
            if (len > 0)
                avpkt.size += len;
        }
    }

    fclose(resultFile);
    fclose(sourceFile);
    free(outbuf);

    avcodec_close(gCodecCtx);
    av_free(gCodecCtx);

    LOGI(10, "end decode.");
}
4

1 回答 1

0

首先,avcodec 将许多有用的消息打印到 stdout/stderr,因此请执行以下操作(至少在出现问题时):

static void cb(void*, int, const char* fmt, va_list vl) {
  __android_log_print(ANDROID_LOG_DEBUG, "avlib", fmt, vl);
}
av_log_set_callback(cb);

我想你有“缺少标题”错误。无论如何,在这里您可以找到几乎可以使用的用法示例:( 答案)使用 ffmpeg API 进行 mp3 解码(缺少标题)

于 2015-01-10T19:42:00.203 回答