解码时出现ffmpeg错误

时间:2013-10-10 09:47:35

标签: android c ffmpeg libav 3gp

我正在使用libav开发一个Android应用程序,我正在尝试使用以下代码解码3gp:

#define simbiLog(...) __android_log_print(ANDROID_LOG_DEBUG, "simbiose", __VA_ARGS__)

...

AVCodec *codec;
AVCodecContext *c = NULL;
int len;
FILE *infile, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;

simbiLog("inbuf size: %d", sizeof(inbuf) / sizeof(inbuf[0]));

av_register_all();
av_init_packet(&avpkt);

codec = avcodec_find_decoder(AV_CODEC_ID_AMR_NB);
if (!codec) {
    simbiLog("codec not found");
    return ERROR;
}

c = avcodec_alloc_context3(codec);
if (!c) {
    simbiLog("Could not allocate audio codec context");
    return ERROR;
}

int open = avcodec_open2(c, codec, NULL);
if (open < 0) {
    simbiLog("could not open codec %d", open);
    return ERROR;
}

infile = fopen(inputPath, "rb");
if (!infile) {
    simbiLog("could not open %s", inputPath);
    return ERROR;
}

outfile = fopen(outputPath, "wb");
if (!outfile) {
    simbiLog("could not open %s", outputPath);
    return ERROR;
}

avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, infile);
int iterations = 0;

while (avpkt.size > 0) {
    simbiLog("iteration %d", (++iterations));
    simbiLog("avpkt.size %d avpkt.data %X", avpkt.size, avpkt.data);
    int got_frame = 0;

    if (!decoded_frame) {
        if (!(decoded_frame = avcodec_alloc_frame())) {
            simbiLog("out of memory");
            return ERROR;
        }
    } else {
        avcodec_get_frame_defaults(decoded_frame);
    }

    //below the error, but it isn't occur on first time, only in 4th loop interation
    len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); 
    if (len < 0) {
        simbiLog("Error while decoding error %d frame %d duration %d", len, got_frame, avpkt.duration);
        return ERROR;
    } else {
        simbiLog("Decoding length %d frame %d duration %d", len, got_frame, avpkt.duration);
    }

    if (got_frame) {
        int data_size = av_samples_get_buffer_size(NULL, c->channels, decoded_frame->nb_samples, c->sample_fmt, 1);
        size_t* fwrite_size = fwrite(decoded_frame->data[0], 1, data_size, outfile);
        simbiLog("fwrite returned %d", fwrite_size);
    }
    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, infile);
        if (len > 0)
            avpkt.size += len;
        simbiLog("fread returned %d", len);
    }
}

fclose(outfile);
fclose(infile);

avcodec_close(c);
av_free(c);
av_free(decoded_frame);

但是我得到了以下日志和错误:

inbuf size: 20488
iteration 1
avpkt.size 3305 avpkt.data BEEED40C
Decoding length 13 frame 1 duration 0
fwrite returned 640
fread returned 0
iteration 2
avpkt.size 3292 avpkt.data BEEED40C
Decoding length 13 frame 1 duration 0
fwrite returned 640
fread returned 0
iteration 3
avpkt.size 3279 avpkt.data BEEED40C
Decoding length 14 frame 1 duration 0
fwrite returned 640
fread returned 0
iteration 4
avpkt.size 3265 avpkt.data BEEED40C
Error while decoding error -1052488119 frame 0 duration 0

我正在尝试解码的音频文件:

$ avprobe blue.3gp 
avprobe version 0.8.6-6:0.8.6-1ubuntu2, Copyright (c) 2007-2013 the Libav developers
  built on Mar 30 2013 22:23:21 with gcc 4.7.2
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'blue.3gp':
  Metadata:
    major_brand     : 3gp4
    minor_version   : 0
    compatible_brands: isom3gp4
    creation_time   : 2013-09-19 18:53:38
  Duration: 00:00:01.52, start: 0.000000, bitrate: 17 kb/s
    Stream #0.0(eng): Audio: amrnb, 8000 Hz, 1 channels, flt, 12 kb/s
    Metadata:
      creation_time   : 2013-09-19 18:53:38

非常感谢!


EDITED

我在关于方法avcodec_decode_audio4的ffmper文档中阅读了以下内容:

@warning The input buffer, avpkt->data must be FF_INPUT_BUFFER_PADDING_SIZE larger than the actual read bytes because some optimized bitstream readers read 32 or 64 bits at once and could read over the end.
@note You might have to align the input buffer. The alignment requirements depend on the CPU and the decoder.

我看到here使用posix_memalign的解决方案,对于android我创建了一个名为memalign的类似方法,所以我做了改动:

删除:

uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];

插入:

int inbufSize = sizeof(uint8_t) * (AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
uint8_t *inbuf = memalign(FF_INPUT_BUFFER_PADDING_SIZE, inbufSize);
simbiLog("inbuf size: %d", inbufSize);
for (; inbufSize >= 0; inbufSize--)
    simbiLog("inbuf position: %d index: %p", inbufSize, &inbuf[inbufSize]);

我得到了正确的记忆序列位置,但错误没有改变。

一个出口:

inbuf position: 37 index: 0x4e43d745
inbuf position: 36 index: 0x4e43d744
inbuf position: 35 index: 0x4e43d743
inbuf position: 34 index: 0x4e43d742
inbuf position: 33 index: 0x4e43d741
inbuf position: 32 index: 0x4e43d740
inbuf position: 31 index: 0x4e43d73f
inbuf position: 30 index: 0x4e43d73e
inbuf position: 29 index: 0x4e43d73d
inbuf position: 28 index: 0x4e43d73c
inbuf position: 27 index: 0x4e43d73b
inbuf position: 26 index: 0x4e43d73a
inbuf position: 25 index: 0x4e43d739
inbuf position: 24 index: 0x4e43d738
inbuf position: 23 index: 0x4e43d737
inbuf position: 22 index: 0x4e43d736
inbuf position: 21 index: 0x4e43d735
inbuf position: 20 index: 0x4e43d734
inbuf position: 19 index: 0x4e43d733

1 个答案:

答案 0 :(得分:1)

您正在尝试解码而不进行多路分解。