Audio coding package FFMPEG

FFMPEG 4.0 for Android preparations

FFMPEG4.0 audio decoding decapsulation

The following function method based on the latest FFMPEG 4.0 (4.X):

This article focuses on how to get raw data from a pcm file, a file generated audio format we need to use the original data, combined with the previous FFMPEG4.0 audio decoding solution package , you will be able to achieve audio format conversion.

PCM data read from a file generated MP3 format.
First, the initialization output

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

The following variables are not necessary, which kept the output format information, comprising generating audio and video encoding format.

AVOutputFormat *ofmt;
ofmt = fmt_ctx->oformat;

Second, prepare the encoder, stream encoding parameter set

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

Third, the open encoder, the number of samples to obtain a data

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

Fourth, the initialization frame and 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 需要申请的字节数
    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);

The above method of the frame data to the memory allocation can be achieved (sample the method) by calling the following methods:
ret = av_frame_get_buffer(frame, 0);

Resampling pcm data is read from a file, where a number of samples obtained conversion data to be read is calculated according to the number of samples generated frame data (the sampling rate is 44,100 samples pcm) (examples herein are on a network ! their example is wrong no problem when the sample rate does not change, there is a change in playing time):
int in_nb_sample = av_rescale_rnd(frame->nb_samples,44100,encodec_ctx->sample_rate,AV_ROUND_UP);

Calculating a desired data conversion buf Size:

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

Fifth, replication parameters, write header information

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

Sixth, the parameter setting resampling

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

Seven coding (coded following is an actual encoding process should be repeated cycles of the following acts, until the file read)
1. pcm read file pointer array prepared resampling approach is to use some ffmpeg Frame interface generation, of the frame were data memory allocation, the essence is the same:

        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. Resampling provided 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. coding (maybe not while loop. After reading the note file needs to send it once, frame pass NULL, mainly in order to flush the encoder)

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. Write terminator
av_write_trailer(fmt_ctx);

Guess you like

Origin blog.51cto.com/4095821/2402673