FFmpeg返回-1的avcodec_decode_audio3 [英] avcodec_decode_audio3 of FFmpeg return -1

查看:154
本文介绍了FFmpeg返回-1的avcodec_decode_audio3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用FFmpeg在android上解码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


函数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 /升ib -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 / b in / arm-linux-androideabi-ar d libavcodec / libavcodec.a reverse.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>
#includelibavcodec / avcodec.h
#includelibavformat / avformat.h

#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
#define LOG_TAGFFmpegTest
#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);
/ *获取源文件的名称* /
sourceFileName =(char *)(* pEnv) - > GetStringUTFChars(pEnv,source_file_name,NULL);
if(sourceFileName == NULL){
LOGE(1,无法获取源文件名!);
exit(1);
}
LOGI(10,源文件名为%s,sourceFileName);

avcodec_init();

av_register_all();

/ *获取格式的源文件到AVFormatContext * /
int lError;
如果((lError = av_open_input_file(& gFormatCtx,sourceFileName,NULL,0,NULL))!= 0){
LOGE(1,错误开源文件:%d,lError);
exit(1);
}
if((lError = av_find_stream_info(gFormatCtx))< 0){
LOGE(1,错误查找流信息:%d,lError);
exit(1);
}
LOGI(10,audio format:%s,gFormatCtx-> iformat-> name);
LOGI(10,audio bitrate:%d,gFormatCtx-> bit_rate);

/ * ???获取音频流的id和源文件的编解码器? * /
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,找不到音频流);
exit(1);
} else if(audioStreamIndex == AVERROR_DECODER_NOT_FOUND){
LOGE(1,发现音频流,但没有找到解码器!);
exit(1);
}
LOGI(10,audio codec:%s,gCodec-> name);

/ *获取编解码器音频流的一部分到AVCodecContext * /
gCodecCtx = gFormatCtx-> streams [audioStreamIndex] - >编解码器;
if(avcodec_open(gCodecCtx,gCodec)< 0){
LOGE(1,无法打开音频编解码器);
exit(1);
}

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

gCodecCtx = avcodec_alloc_context();

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

outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

sourceFile = fopen(sourceFileName,rb);
if(!sourceFile){
LOGE(1,无法打开%s,sourceFileName);
exit(1);
}
/ *获取结果文件的名称* /
resultFileName =(char *)(* pEnv) - > GetStringUTFChars(pEnv,result_file_name,NULL);
LOGI(10,结果文件名为%s,resultFileName);
resultFile = fopen(resultFileName,wb);
if(!resultFile){
LOGE(1,无法创建结果文件);
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);
/ *解码文件* /
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,解码时出错:%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);
免费(outbuf);

avcodec_close(gCodecCtx);
av_free(gCodecCtx);

LOGI(10,end decode);
}


解决方案

首先,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);

我想你有丢失标题错误。无论如何,在这里你可以找到几乎工作的使用示例:
(答案)mp3解码使用ffmpeg API(标题缺失)


I use FFmpeg on android to decode mp3. I set all decoder enable on configure and make the .so file correctly. Here's the .sh which add parameter for configure file:

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

I can read file and get info (decode type\ format type), then I follow the FFmpeg's sample to call avcodec_decode_audio3 to decode audio file, it return -1, decoding failed. Is some body can tell me what is happened, thanks!

#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.");
}

解决方案

First of all, avcodec prints many useful messages to stdout/stderr, so do following (at least while something wrong):

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);

I suppose that you have "missing header" error. Anyway, here you can find almost working usage example: (Answer) mp3 decoding using ffmpeg API (Header missing)

这篇关于FFmpeg返回-1的avcodec_decode_audio3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆