天天看點

VC++ 采用 ffmpeg 提取視訊的音頻 轉碼 wav 播放全程有很大雜音 如何解決,源碼已附上

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32

//Windows

extern "C"

{

#include "libavcodec/avcodec.h"

#include "libavformat/avformat.h"

#include "libswscale/swscale.h"

#include "libavutil/pixfmt.h"

#include <libswresample/swresample.h>

#include <libavfilter/avfilter.h>

#include <libavfilter/avfiltergraph.h>

#include <libavfilter/buffersink.h>

#include <libavfilter/buffersrc.h>

#include <libavutil/samplefmt.h>

#include "libavutil/avutil.h"  

#include "libavutil/opt.h"  

#include "libavutil/pixdesc.h"  

};

#else

//Linux...

#ifdef __cplusplus

extern "C"

{

#endif

#include <libavcodec/avcodec.h>

#include <libavformat/avformat.h>

#include <libswscale/swscale.h>

#include <libavutil/pixfmt.h>

#ifdef __cplusplus

};

#endif

#endif

#include <stdio.h>

#include<windows.h>

#include <conio.h>

#include <ctype.h>

#include <iostream>

#include <vector>

#include <signal.h>

#include <assert.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000

static int is_full_screen;

static int64_t audio_callback_time;

static   void writeWavHeader(AVCodecContext *pCodecCtx, AVFormatContext *pFormatCtx, FILE *audioFile) {

    //wav檔案有44位元組的wav頭,是以要寫44位元組的wav頭

    int8_t *data;

    int32_t long_temp;

    int16_t short_temp;

    int16_t BlockAlign;

    int bits = 16;

    int32_t fileSize;

    int32_t audioDataSize;

    switch (pCodecCtx->sample_fmt) {

    case AV_SAMPLE_FMT_S16:

        bits = 16;

        break;

    case AV_SAMPLE_FMT_S32:

        bits = 32;

        break;

    case AV_SAMPLE_FMT_U8:

        bits = 8;

        break;

    default:

        bits = 16;

        break;

    }

    audioDataSize = (pFormatCtx->duration)*(bits / 8)*(pCodecCtx->sample_rate)*(pCodecCtx->channels);

    fileSize = audioDataSize + 36;

    data = (int8_t *)"RIFF";

    fwrite(data, sizeof(char), 4, audioFile);

    fwrite(&fileSize, sizeof(int32_t), 1, audioFile);

    data = (int8_t *)"WAVE";

    fwrite(data, sizeof(char), 4, audioFile);

    data = (int8_t *)"fmt ";

    fwrite(data, sizeof(char), 4, audioFile);

    long_temp = 16;

    fwrite(&long_temp, sizeof(int32_t), 1, audioFile);

    short_temp = 0x01;

    fwrite(&short_temp, sizeof(int16_t), 1, audioFile);

    short_temp = (pCodecCtx->channels);

    fwrite(&short_temp, sizeof(int16_t), 1, audioFile);

    long_temp = (pCodecCtx->sample_rate);

    fwrite(&long_temp, sizeof(int32_t), 1, audioFile);

    long_temp = (bits / 8)*(pCodecCtx->channels)*(pCodecCtx->sample_rate);

    fwrite(&long_temp, sizeof(int32_t), 1, audioFile);

    BlockAlign = (bits / 8)*(pCodecCtx->channels);

    fwrite(&BlockAlign, sizeof(int16_t), 1, audioFile);

    short_temp = (bits);

    fwrite(&short_temp, sizeof(int16_t), 1, audioFile);

    data = (int8_t *) "data";

    fwrite(data, sizeof(char), 4, audioFile);

    fwrite(&audioDataSize, sizeof(int32_t), 1, audioFile);

}

int main()

{

    char *filename = "ffmpegTest.mp4";

    AVFormatContext *pFormatCtx = NULL;

    int audioStream = -1;

    int i;

    int iFrame = 0;

    AVCodecContext *pCodecCtx;

    AVCodec *pCodec = NULL;

    static AVPacket packet;

    uint8_t *pktData = NULL;

    int pktSize;

    int outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;

    uint8_t *inbuf = (uint8_t *)av_malloc(outSize);

    FILE *wavFile = NULL;

    int32_t audioFileSize = 0;

    av_register_all();

    if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) < 0)

    {

        printf("Could not open input file %s\n", filename);

        return 0;

    }

    if (av_find_stream_info(pFormatCtx)<0)

    {

        printf("Could not find stream information\n");

    }

    av_dump_format(pFormatCtx, 0, filename, 0);

    for (i = 0; i<pFormatCtx->nb_streams; i++) {

        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {

            audioStream = i;

            break;

        }

    }

    pCodecCtx = pFormatCtx->streams[audioStream]->codec;

    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

  //open codec 

    if (avcodec_open2(pCodecCtx, pCodec, NULL)<0) {

        printf("Error avcodec_open failed.\n");

        return 1;

    }

    wavFile = fopen("E:\\flv\\yu.wav", "wb");

    if (wavFile == NULL)

    {

        printf("open error\n");

        return 1;

    }

    //write wav header

    writeWavHeader(pCodecCtx, pFormatCtx, wavFile);

    //start codec

    av_free_packet(&packet);

    while (av_read_frame(pFormatCtx, &packet) >= 0) {

        if (packet.stream_index == audioStream)

        {

            int len = 0;

            if ((iFrame++) >= 4000)

                break;

            pktData = packet.data;

            pktSize = packet.size;

            while (pktSize>0) {

                outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;

                len = avcodec_decode_audio3(pCodecCtx, (short *)inbuf, &outSize, &packet);

                if (len<0) {

                    printf("Error while decoding\n");

                    break;

                }

                if (outSize>0) {

                    audioFileSize += outSize;

                    fwrite(inbuf, 1, outSize/2, wavFile);

                    fflush(wavFile);

                }

                pktSize -= len;

                pktData += len;

            }

        }

        av_free_packet(&packet);

    }

    fclose(wavFile);

    av_free(inbuf);

    if (pCodecCtx != NULL) {

        avcodec_close(pCodecCtx);

    }

    av_close_input_file(pFormatCtx);

    printf("輸入任意鍵退出!");

    getchar();

}