【问题标题】:ffmpeg function avcodec_receive_frame always return EAGAIN errorffmpeg 函数 avcodec_receive_frame 总是返回 EAGAIN 错误
【发布时间】:2019-11-29 16:00:08
【问题描述】:

我在iOS上用ffmpeg解码he-aac音频文件,解码器是libfdk_aac,音频文件如下: https://cdn.perterpon.com/listen/test/bbc.mp4 这是av_dump_format 结果:

Metadata:
    major_brand     : iso6
    minor_version   : 0
    compatible_brands: iso6dash
  Duration: N/A, bitrate: N/A
    Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, 2 channels (default)
    Metadata:
      handler_name    : USP Sound Handler

av_read_frameavcodec_send_packet 返回 0,但 avcodec_receive_frame 始终返回 AVERROR(EAGAIN)

我试过ffmpeg命令行工具:ffmpeg -i bbc.mp4 bbc.mp3,成功了,在iOS上播放mp3文件很好。

这是我的代码:

av_register_all();
AVFormatContext *avFormatContext = avformat_alloc_context();
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"bbc" ofType:@"mp4"];

int ret;
ret = avformat_open_input(&avFormatContext, [filePath UTF8String], NULL, NULL);
if (0 != ret) {
    NSLog(@"avformat_open_input failed: %d", ret);
}

ret = avformat_find_stream_info(avFormatContext, NULL);
if (0 != ret) {
    NSLog(@"avformat_find_stream_info: %d", ret);
}

// the libfdk_aac decoder
AVCodec *codec = avcodec_find_decoder_by_name("libfdk_aac");
AVCodecContext *codecContext = avcodec_alloc_context3(codec);

ret = avcodec_open2(codecContext, codec, NULL);
if (0 != ret) {
    NSLog(@"avcodec_open2 faild: %d", ret);
}

AVFrame *frame = av_frame_alloc();
AVPacket packet;
av_init_packet(&packet);

// start read data and decode data
while (true) {
    ret = av_read_frame(avFormatContext, &packet);
    if (0 != ret) {
        break;
    }
    ret = avcodec_send_packet(codecContext, &packet);
    if (ret != 0) {
        NSLog(@"send package with error: %d", ret);
        continue;
        break;
    }
    while (true) {
        // the ret below is always return -35, means AVERROR(EAGAIN)
        ret = avcodec_receive_frame(codecContext, frame);
        if (ret == AVERROR(EAGAIN)) {
            NSLog(@"avcodec_receive_frame with EAGAIN error: %d", ret);
            break;
        } else if (ret == AVERROR_EOF) {
            NSLog(@"end of file");
            break;
        }
    }
    if (ret == AVERROR(EAGAIN)) {
        continue;
    }
}

我尝试将bbc.mp4文件替换为bbc.mp3文件,并将解码器更改为:AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_MP3);,一切正常。非常非常非常感谢。

【问题讨论】:

    标签: ios ffmpeg


    【解决方案1】:

    当 avcodec_receive_frame 返回 EAGAIN 时,您必须在再次调用 avcodec_receive_frame 之前使用更多数据(或流末尾的空数据包)调用 avcodec_send_packet。

    【讨论】:

    • 我试过,当收到AVERROR(EAGAIN)时,做av_read_frame(avFormatContext, &packet);avcodec_send_packet(codecContext, &packet);,之后avcodec_receive_frame(codecContext, frame);总是得到AVERROR(EAGAIN)
    • 这个逻辑已经在代码中了,我想。可能是我错了,哈哈
    • 内部的while循环是一个无限循环。当返回 EAGAIN 时,它会调用 continue 继续循环并获得 EAGAIN。在循环被破坏(或删除)之前,您将始终获得 EAGAIN
    • 对不起,我的错误,当我发布这段代码时,我做了一些编辑,已经更新了我的代码,内部循环中的continue更改为break,结果是一样的。
    猜你喜欢
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2019-06-14
    • 2018-01-03
    相关资源
    最近更新 更多