FFMPEG音頻封裝編碼

FFMPEG 4.0 for Android 準備工作

創(chuàng)新互聯(lián)建站-專業(yè)網站定制、快速模板網站建設、高性價比二道江網站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式二道江網站制作公司更省心,省錢,快速模板網站建設找我們,業(yè)務覆蓋二道江地區(qū)。費用合理售后完善,10余年實體公司更值得信賴。

FFMPEG4.0 音頻解碼解封裝

下面的函數方法基于最新的FFMPEG 4.0(4.X):

本文主要講如何從一個pcm文件中拿到原始數據,用原始數據生成一個我們需要的音頻格式文件,結合上一篇的FFMPEG4.0 音頻解碼解封裝,你將能夠實現音頻格式轉換.

從PCM文件中讀取數據生成MP3格式文件。
一、初始化輸出

 AVFormatContext *fmt_ctx;
    int ret = avformat_alloc_output_context2(&fmt_ctx,NULL,NULL,out_file);
 ret = avio_open(&fmt_ctx->pb,out_file,AVIO_FLAG_WRITE);

下面的變量不是必須的,里面存了輸出格式的信息,包含生成的音視頻編碼格式。

AVOutputFormat *ofmt;
ofmt = fmt_ctx->oformat;

二、準備編碼器、流,設置編碼參數

encodec = avcodec_find_encoder(AV_CODEC_ID_MP3);//可通過ofmt->audio_codec得到格式
st = avformat_new_stream(fmt_ctx,encodec);
encodec_ctx = avcodec_alloc_context3(encodec);

encodec_ctx->sample_rate = 44100;
encodec_ctx->bit_rate = 64000;
encodec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
encodec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
encodec_ctx->channels = av_get_channel_layout_nb_channels(encodec_ctx->channel_layout);

三、打開編碼器,得到一幀數據的采樣數

ret = avcodec_open2(encodec_ctx,encodec,NULL);
int encode_nb_sample = encodec_ctx->frame_size;

四、初始化frame與packet

    frame = av_frame_alloc();
    pkt = av_packet_alloc();
    frame->nb_samples = encode_nb_sample;
    frame->format = encodec_ctx->sample_fmt;
    frame->channel_layout = encodec_ctx->channel_layout;

    //frame.data 需要申請的字節(jié)數
    int size = av_samples_get_buffer_size(NULL,encodec_ctx->channels,encode_nb_sample,encodec_ctx->sample_fmt,1);
    uint8_t *frame_buf = (uint8_t *) av_malloc(size);
avcodec_fill_audio_frame(frame,encodec_ctx->channels,encodec_ctx->sample_fmt,frame_buf,size,1);

上面的給frame內data分配內存的方法可以通過調用如下方法達到(sample內方法):
ret = av_frame_get_buffer(frame, 0);

重采樣的數據從pcm文件中讀取,這里根據生成的一幀數據的樣本數計算得出轉換一幀數據需要讀取的樣本數(pcm樣本的采樣率是44100)(網絡上的示例這里都是錯的!他們的例子在不改變采樣率時沒問題,一改變就有播放時間變化):
int in_nb_sample = av_rescale_rnd(frame->nb_samples,44100,encodec_ctx->sample_rate,AV_ROUND_UP);

計算轉換需要的一幀數據buf大?。?/p>

int readSize = in_nb_sample * av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO) * av_get_bytes_per_sample(in_fmt);
char *read_buf = (char*)malloc(readSize);

五、復制參數、寫頭信息

    avcodec_parameters_from_context(st->codecpar,encodec_ctx);
    avformat_write_header(fmt_ctx,NULL);

六、設置重采樣參數

    swc = swr_alloc();
    av_opt_set_int(swc,"in_channel_layout",AV_CH_LAYOUT_STEREO,0);
    av_opt_set_int(swc,"in_sample_rate",in_sample_rate,0);
    av_opt_set_sample_fmt(swc,"in_sample_fmt",in_fmt,0);

    av_opt_set_int(swc,"out_channel_layout",encodec_ctx->channel_layout,0);
    av_opt_set_int(swc,"out_sample_rate",encodec_ctx->sample_rate,0);
    av_opt_set_sample_fmt(swc,"out_sample_fmt",encodec_ctx->sample_fmt,0);
ret = swr_init(swc);

七、編碼(下面是一幀編碼,實際編碼過程應該是反復循環(huán)下面的行為,直到文件讀完)
1.讀取pcm文件,準備重采樣的數組指針,有些做法是利用ffmpeg的接口生成frame,對frame進行data內存分配,實質都是一樣:

        if (fread(read_buf, 1, readSize, infile) < 0) {
            printf("文件讀取錯誤!\n");
            return -1;
        } else if (feof(infile)) {
            break;
        }
        //重采樣源數據
        const uint8_t *indata[AV_NUM_DATA_POINTERS] = {0};
        indata[0] = (uint8_t *) read_buf;

2.重采樣,設置pts

        int len = swr_convert(swc, frame->data, frame->nb_samples,indata, in_nb_sample);
        LOGV("len = %d\n",len);
        frame->pts = apts;
        apts += av_rescale_q(len,(AVRational){1,encodec_ctx->sample_rate},encodec_ctx->time_base);

3.編碼(也許不用while循環(huán)。注意文件讀完后還需呀send一次,frame傳NULL,主要為了flush編碼器)

ret = avcodec_send_frame(encodec_ctx, frame);

        while(ret >= 0) {
            LOGV("receiver\n");
            ret = avcodec_receive_packet(encodec_ctx, pkt);
            if (ret < 0) {
                av_log(NULL, AV_LOG_ERROR, "%s,ret = %d\n", "avcodec_receive_packet!error ",ret);
                break;
            }
            pkt->stream_index = st->index;
            av_log(NULL, AV_LOG_DEBUG, "第%d幀\n", i);
            pkt->pts = av_rescale_q(pkt->pts, encodec_ctx->time_base, st->time_base);
            pkt->dts = av_rescale_q(pkt->dts, encodec_ctx->time_base, st->time_base);
            pkt->duration = av_rescale_q(pkt->duration, encodec_ctx->time_base, st->time_base);
            LOGV("duration = %d,dts=%d,pts=%d\n",pkt->duration,pkt->dts,pkt->pts);
            ret = av_write_frame(fmt_ctx, pkt);
            if (ret < 0) {
                av_log(NULL, AV_LOG_ERROR, "av_write_frame error!");
            }
            av_packet_unref(pkt);
        }

4.寫結束符
av_write_trailer(fmt_ctx);

網站欄目:FFMPEG音頻封裝編碼
鏈接分享:http://muchs.cn/article38/phodsp.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供網站設計公司、網站制作、微信公眾號、Google網站維護、用戶體驗

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都網頁設計公司