使用FFmpeg进行WMA解码

4

我刚接触 ffmpeg,并尝试使用 api-example.c 解码 wma 文件。但是,当我运行程序时,它给出了一个错误信息:

"frame_len overflow"。有人知道如何解决这个错误吗?

以下是我的代码:

extern "C" {
#include <avcodec.h>
#include "../libavcodec/avcodec.h"
#include <avformat.h>
}

#include <iostream>
#include <assert.h>
#include <windows.h>
#include <mmsystem.h>
#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096

int main(int argc, char *argv[]) {
    avcodec_init();
    avcodec_register_all();
    //avdevice_register_all();
    av_register_all();

    AVCodec *codec;
    AVCodecContext *c= NULL;

    AVCodec *ocodec;
    AVCodecContext *oc= NULL;

    int out_size, len,out_size2;
    FILE *f, *outfile;
    uint8_t *outbuf;
    uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];

    AVPacket avpkt;
    char* outfilename="test.wma";
    char* filename="Beethoven's.wma";
    AVFormatContext *pFormatCtx;

    WAVEFORMATEX* wfx=new WAVEFORMATEX;

    int ret;
    ret=av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL);

    if(ret!=0)
    {
        std::cout<<"cannot open file!"<<std::endl;
        exit(1);
    }

    if(av_find_stream_info(pFormatCtx)<0)
    {
        std::cout<<"cannot find stream!"<<std::endl;
        exit(1);
    }

    int audioStream;
    AVCodecContext *pCodecCtx;
    // Find the first video stream
    audioStream=-1;
    for(int i=0; i<pFormatCtx->nb_streams; i++)
        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
        {
            audioStream=i;
            break;
        }
    if(audioStream==-1)
    {
        std::cout<<"cannot find audio!"<<std::endl;
    }

    // Get a pointer to the codec context for the audio stream
    pCodecCtx=pFormatCtx->streams[audioStream]->codec;
    av_init_packet(&avpkt);

    printf("Audio decoding\n");

    /* find the suitable audio decoder */
    codec = avcodec_find_decoder(pCodecCtx->codec_id);

    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    if(codec->capabilities & CODEC_CAP_TRUNCATED)
        pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;

    //open the codec (for decoding)
    int test = avcodec_open(pCodecCtx, codec);
    if (test < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    //find mp3 encoder
    ocodec = avcodec_find_encoder(CODEC_ID_MP3);
    if (!ocodec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    //allocate context
    oc= avcodec_alloc_context();
    /* put sample parameters */
    oc->bit_rate = 64000;
    oc->sample_rate = 44100;
    oc->channels = 1;
    /* open it */
    if (avcodec_open(oc, ocodec) < 0) {
        fprintf(stderr, "could not open encoding codec\n");
        exit(1);
    }

    //buffer
    outbuf = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

    //open inputfile
    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    //open outputfile
    outfile = fopen(outfilename, "wb");

    if (!outfile) {
        av_free(c);
        exit(1);
    }

    /* decode until eof */
    avpkt.data = inbuf;
    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

    //while there is still data
    while (avpkt.size > 0) {
        std::cout<<"decoding..."<<std::endl;
        out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
        //decode
        len = avcodec_decode_audio3(pCodecCtx, (short *)outbuf, &out_size, &avpkt);

        if (len < 0) {
            fprintf(stderr, "Error while decoding\n");
            exit(1);
        }

        if (out_size > 0) {
            /* if a frame has been decoded, output it */
            std::cout<<"1 frame decoded!"<<std::endl;
            out_size2 = avcodec_encode_audio(oc, outbuf, out_size, (short*)outbuf);
            fwrite(outbuf, 1, out_size2, outfile);
        }

        //subtract data from whatever decode function returns

        avpkt.size -= len;

        avpkt.data += len;

        if (avpkt.size < AUDIO_REFILL_THRESH) {

            /* Refill the input buffer, to avoid trying to decode

            * incomplete frames. Instead of this, one could also use

            * a parser, or use a proper container format through

            * libavformat. */

            memmove(inbuf, avpkt.data, avpkt.size);

            avpkt.data = inbuf;

            len = fread(avpkt.data + avpkt.size, 1,

                        AUDIO_INBUF_SIZE - avpkt.size, f);

            if (len > 0)

                avpkt.size += len;

        }



    }

    fclose(outfile);

    fclose(f);

    free(outbuf);

    avcodec_close(c);

    av_free(c);



}

我卡在这里很长时间了,请帮帮我。 有人知道我的代码有什么问题吗?

谢谢,

Izak


请使用适当的缩进和空格使其易读...您在哪里得到了“frame_len overflow”? - ronag
当我运行程序时,它返回一个错误,说“frame_len溢出”。 - Izak
你主要是想解码WMA还是学习如何使用FFmpeg?对于WMA,如果你在Windows上运行,有一个很好的替代品可以使用,不需要使用FFmpeg。 - Daniel Mošmondor
我想解码wma。如果别无选择,我可以尝试其他替代方案,但希望能使用ffmpeg来解码wma。 - Izak
1
有人知道我的代码哪里出了问题吗? - Izak
1个回答

0
使用调试信息来确定故障点。尽管我坚信这个错误发生在编码时,因为您正在使用相同的缓冲区和相应的缓冲区大小。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接