c++ - 使用 ffmpeg 解码 Wma

标签 c++ ffmpeg libavcodec libavformat

我是 ffmpeg 的新手,我尝试使用 api-example.c 来解码 wma 文件。但是当我运行程序时,它给了我一个错误提示

“frame_len 溢出”。有谁知道如何解决这个错误?

这是我的代码:

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



}

这个问题我纠结了很久。请帮我。 有人知道我的代码有什么问题吗?

谢谢,

伊扎克

最佳答案

使用调试消息来确定故障点。 尽管我强烈认为编码时会发生此错误,因为您使用的是相同的缓冲区和各自的缓冲区大小。

关于c++ - 使用 ffmpeg 解码 Wma,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4487263/

相关文章:

c++ - 为什么 OpenGL 着色器无法正确编译?

c++ - 如何在 .pri 文件的内容前加上路径?

python - 如何使用大于 2 GB 的 OpenCV 编写 avi 文件?

ffmpeg - 在编码时强制自定义 H.264 帧内(关键帧)?

c++ - FFmpeg 解码和转换 RGB sws_scale 错误

c++ - 强制返回的 const 值 move 而不是复制

c# - C++/命令行界面 : Implementing an abstract C# class that implements INotifyPropertyChanged results in C++ compiler error C3766

ffmpeg - 从非常短的 MP4 (AVC) 输入创建 TS 输出

c++ - 复制解码的 ffmpeg AVFrame

c++ - 使用 C++ 访问网络摄像头的 FFMPEG