我在android上使用FFmpeg来解码mp3。我在configure上设置所有解码器启用并正确生成.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.");
}
答案 0 :(得分: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);
我认为你有#34;缺少标题&#34;错误。无论如何,在这里你可以找到几乎工作的用法示例: (Answer) mp3 decoding using ffmpeg API (Header missing)