FFMPEG 音频编码

 avcodec_send_frame  

avcodec_receive_packet

格式s16le,planar

#include 
#include 
#include 

extern "C"
{
#include 
}
static void encode(AVCodecContext *cdc_ctx, AVFrame *frame, AVPacket *pkt, FILE *fp_out)
{
    int ret = 0;

    if ((ret = avcodec_send_frame(cdc_ctx, frame)) < 0)
    {
        fprintf(stderr, "avcodec_send_frame failed.\n");
        exit(1);
    }

    while ((ret = avcodec_receive_packet(cdc_ctx, pkt)) >= 0)
    {
        printf("Write (size=%d) packet.\n", pkt->size);
        fwrite(pkt->data, 1, pkt->size, fp_out);
        av_packet_unref(pkt);
    }

    if ((ret != AVERROR(EAGAIN)) && (ret != AVERROR_EOF))
    {
        fprintf(stderr, "avcodec_receive_packet failed.\n");
        exit(1);
    }
}

void encode_audio(const char *input_file, const char *output_file)
{
    int ret = 0;
    int data_size = 0;
    AVCodec *codec = NULL;
    AVCodecContext *cdc_ctx = NULL;
    AVPacket *pkt = NULL;
    AVFrame *frame = NULL;
    FILE *fp_in, *fp_out;

    if ((codec = avcodec_find_encoder(AV_CODEC_ID_MP3)) == NULL)
    {
        fprintf(stderr, "avcodec_find_encoder_by_name failed.\n");
        goto ret1;
    }

    if ((cdc_ctx = avcodec_alloc_context3(codec)) == NULL)
    {
        fprintf(stderr, "avcodec_alloc_context3 failed.\n");
        goto ret1;
    }

    /*encode speech_mono_16kHz_s16le.pcm */
    cdc_ctx->bit_rate = 640000;
    cdc_ctx->sample_fmt = AV_SAMPLE_FMT_S16P;
    cdc_ctx->sample_rate = 16000;
    cdc_ctx->channel_layout = av_get_channel_layout("stereo");
    cdc_ctx->channels = av_get_channel_layout_nb_channels(cdc_ctx->channel_layout);

    if ((ret = avcodec_open2(cdc_ctx, codec, NULL)) < 0)
    {
        fprintf(stderr, "avcodec_open2 failed.\n");
        goto ret2;
    }

    if ((pkt = av_packet_alloc()) == NULL)
    {
        fprintf(stderr, "av_packet_alloc failed.\n");
        goto ret3;
    }

    if ((frame = av_frame_alloc()) == NULL)
    {
        fprintf(stderr, "av_frame_alloc failed.\n");
        goto ret4;
    }
    frame->nb_samples = cdc_ctx->frame_size;
    frame->format = cdc_ctx->sample_fmt;
    frame->channel_layout = cdc_ctx->channel_layout;

    if ((ret = av_frame_get_buffer(frame, 0)) < 0)
    {
        fprintf(stderr, "av_frame_get_buffer failed.\n");
        goto ret5;
    }

    if ((fp_in = fopen(input_file, "rb")) == NULL)
    {
        fprintf(stderr, "fopen %s failed.\n", input_file);
        goto ret5;
    }
    if ((fp_out = fopen(output_file, "wb")) == NULL)
    {
        fprintf(stderr, "fopen %s failed.\n", output_file);
        goto ret6;
    }

    data_size = av_get_bytes_per_sample(cdc_ctx->sample_fmt);

    while (feof(fp_in) == 0)
    {
        int i = 0, ch = 0;

        if ((ret = av_frame_make_writable(frame)) < 0)
        {
            fprintf(stderr, "frame is not writable.\n");
            goto ret7;
        }
        //Packed: L R L R L R L R
        //Planar: L L L L R R R R
        for (i = 0; i < frame->nb_samples; i++)
        {
            for (ch = 0; ch < cdc_ctx->channels; ch++)
            {
                fread(frame->data[ch] + data_size * i, 1, data_size, fp_in);
            }
        }

        encode(cdc_ctx, frame, pkt, fp_out);
    }

    encode(cdc_ctx, NULL, pkt, fp_out);


    fclose(fp_out);
    fclose(fp_in);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    avcodec_close(cdc_ctx);
    avcodec_free_context(&cdc_ctx);
    return;
ret7:
    fclose(fp_out);
ret6:
    fclose(fp_in);
ret5:
    av_frame_free(&frame);
ret4:
    av_packet_free(&pkt);
ret3:
    avcodec_close(cdc_ctx);
ret2:
    avcodec_free_context(&cdc_ctx);
ret1:
    exit(1);
}

int main(int argc, const char *argv[])
{

    encode_audio("/home/lili/Videos/16k_s16le_stereo.pcm", "/home/lili/Videos/output.aac");

    return 0;
}

extern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
}
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
	const enum AVSampleFormat *p = codec->sample_fmts;

	while (*p != AV_SAMPLE_FMT_NONE) {
		if (*p == sample_fmt)
			return 1;
		p++;
	}
	return 0;
}

/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec *codec)
{
	const int *p;
	int best_samplerate = 0;

	if (!codec->supported_samplerates)
		return 44100;

	p = codec->supported_samplerates;
	while (*p) {
		if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
			best_samplerate = *p;
		p++;
	}
	return best_samplerate;
}

/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec)
{
	const uint64_t *p;
	uint64_t best_ch_layout = 0;
	int best_nb_channels = 0;

	if (!codec->channel_layouts)
		return AV_CH_LAYOUT_STEREO;

	p = codec->channel_layouts;
	while (*p) {
		int nb_channels = av_get_channel_layout_nb_channels(*p);

		if (nb_channels > best_nb_channels) {
			best_ch_layout = *p;
			best_nb_channels = nb_channels;
		}
		p++;
	}
	return best_ch_layout;
}
int  main()
{
	av_register_all();
	AVCodec * codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
	if (codec == NULL)
	{
		fprintf(stderr, "Codec not found!\n");
		return -1;
	}

	AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
	if (codec_ctx == NULL)
	{
		fprintf(stderr, "Could not allocate audio codec context!\n");
		return -1;
	}

	//put sample param
	codec_ctx->bit_rate = 64000;

	/* check that the encoder supports s16 pcm input */
	codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;
	if (!check_sample_fmt(codec, codec_ctx->sample_fmt)) {
		fprintf(stderr, "Encoder does not support sample format %s",
			av_get_sample_fmt_name(codec_ctx->sample_fmt));
		exit(1);
	}
	/* select other audio parameters supported by the encoder */
	codec_ctx->sample_rate = select_sample_rate(codec);
	codec_ctx->channel_layout = select_channel_layout(codec);
	codec_ctx->channels = av_get_channel_layout_nb_channels(codec_ctx->channel_layout);

	if (avcodec_open2(codec_ctx, codec, NULL) < 0)
	{
		fprintf(stderr, "Could not open codec!\n");
		return -1;
	}

	AVFrame *frame = av_frame_alloc();
	if (!frame) {
		fprintf(stderr, "Could not allocate audio frame\n");
		return -1;
	}
	
	frame->nb_samples = codec_ctx->frame_size;
	frame->format = codec_ctx->sample_fmt;
	frame->channel_layout = codec_ctx->channel_layout;


	int ret = av_frame_get_buffer(frame, 0);
	if (ret < 0)
	{
		fprintf(stderr, "av_frame_get_buffer error!\n");
		return -1;
	}
	const char *name = "./test.aac";
	FILE *file = fopen(name, "wb");
	if (!file) {
		fprintf(stderr, "Could not open %s\n", name);
		exit(1);
	}

	/* encode a single tone sound */
	float t = 0.01, tincr;
	AVPacket pkt;
	tincr = 2 * M_PI * 440.0 / codec_ctx->sample_rate;
	for (int i = 0; i < 200; i++) 
	{
		av_init_packet(&pkt);
		pkt.data = NULL; // packet data will be allocated by the encoder
		pkt.size = 0;

		/* make sure the frame is writable -- makes a copy if the encoder
		* kept a reference internally */
		ret = av_frame_make_writable(frame);
		if (ret < 0)
			exit(1);
		uint16_t *samples = (uint16_t*)frame->data[0];

		for (int j = 0; j < codec_ctx->frame_size; j++) {
			samples[2 * j] = (int)(sin(t) * 10000);

			for (int k = 1; k < codec_ctx->channels; k++)
				samples[2 * j + k] = samples[2 * j];
			t += tincr;
		}
		/* encode the samples */
		int got_output = 0;
		ret = avcodec_encode_audio2(codec_ctx, &pkt, frame, &got_output);
		if (ret < 0) {
			fprintf(stderr, "Error encoding audio frame\n");
			exit(1);
		}
		if (got_output) {
			fwrite(pkt.data, 1, pkt.size, file);
			av_packet_unref(&pkt);
		}
	}

	/* get the delayed frames */
	for (int got_output = 1; got_output;) {
		ret = avcodec_encode_audio2(codec_ctx, &pkt, NULL, &got_output);
		if (ret < 0) {
			fprintf(stderr, "Error encoding frame\n");
			exit(1);
		}

		if (got_output) {
			fwrite(pkt.data, 1, pkt.size, file);
			av_packet_unref(&pkt);
		}
	}
	fclose(file);

	av_frame_free(&frame);
	avcodec_free_context(&codec_ctx);

}

使用 avcodec_encode_audio2

#include 
#include 
#include 

extern "C"
{
#include 
}

void encode_audio(const char *input_file, const char *output_file)
{
    int ret = 0;
    int data_size = 0;
    AVCodec *codec = NULL;
    AVCodecContext *cdc_ctx = NULL;
    AVPacket *pkt = NULL;
    AVFrame *frame = NULL;
    FILE *fp_in, *fp_out;

    int got_data = 0;
    if ((codec = avcodec_find_encoder(AV_CODEC_ID_MP3)) == NULL)
    {
        fprintf(stderr, "avcodec_find_encoder_by_name failed.\n");
        goto ret1;
    }

    if ((cdc_ctx = avcodec_alloc_context3(codec)) == NULL)
    {
        fprintf(stderr, "avcodec_alloc_context3 failed.\n");
        goto ret1;
    }

#if 1 	/*encode short_mixed_stereo_48.pcm*/
    cdc_ctx->bit_rate = 64000;
    cdc_ctx->sample_fmt = AV_SAMPLE_FMT_S16P;
    cdc_ctx->sample_rate = 48000;
    cdc_ctx->channel_layout = av_get_channel_layout("stereo");
    cdc_ctx->channels = av_get_channel_layout_nb_channels(cdc_ctx->channel_layout);

#else 	/*encode beijingbeijing_8k_16bits_memo.pcm*/
    cdc_ctx->bit_rate = 64000;
    cdc_ctx->sample_fmt = AV_SAMPLE_FMT_S16P;
    cdc_ctx->sample_rate = 8000;
    cdc_ctx->channel_layout = av_get_channel_layout("mono");
    cdc_ctx->channels = av_get_channel_layout_nb_channels(cdc_ctx->channel_layout);
#endif

    if ((ret = avcodec_open2(cdc_ctx, codec, NULL)) < 0)
    {
        fprintf(stderr, "avcodec_open2 failed.\n");
        goto ret2;
    }

    if ((pkt = av_packet_alloc()) == NULL)
    {
        fprintf(stderr, "av_packet_alloc failed.\n");
        goto ret3;
    }

    if ((frame = av_frame_alloc()) == NULL)
    {
        fprintf(stderr, "av_frame_alloc failed.\n");
        goto ret4;
    }
    frame->nb_samples = cdc_ctx->frame_size;
    frame->format = cdc_ctx->sample_fmt;
    frame->channel_layout = cdc_ctx->channel_layout;

    if ((ret = av_frame_get_buffer(frame, 0)) < 0)
    {
        fprintf(stderr, "av_frame_get_buffer failed.\n");
        goto ret5;
    }

    if ((fp_in = fopen(input_file, "rb")) == NULL)
    {
        fprintf(stderr, "fopen %s failed.\n", input_file);
        goto ret5;
    }
    if ((fp_out = fopen(output_file, "wb")) == NULL)
    {
        fprintf(stderr, "fopen %s failed.\n", output_file);
        goto ret6;
    }



    data_size = av_get_bytes_per_sample(cdc_ctx->sample_fmt);
    fprintf(stderr, "data_size = %d\n", data_size);
    while (feof(fp_in) == 0)
    {
        int i = 0, ch = 0;

        if ((ret = av_frame_make_writable(frame)) < 0)
        {
            fprintf(stderr, "frame is not writable.\n");
            goto ret7;
        }

        for (i = 0; i < frame->nb_samples; i++)
        {
            for (ch = 0; ch < cdc_ctx->channels; ch++)
            {
                fread(frame->data[ch] + data_size * i, 1, data_size, fp_in);
            }
        }


        if ((ret = avcodec_encode_audio2(cdc_ctx, pkt, frame, &got_data)) < 0)
        {
            fprintf(stderr, "avcodec_encode_audio2 failed.\n");
            exit(1);
        }
        if(got_data)
        {
            int nwrite = fwrite(pkt->data, 1, pkt->size, fp_out);
            fprintf(stdout, "nwrite %d data.\n", nwrite);
            av_packet_unref(pkt);
        }
    }

    /* get the delayed frames */
    for (int got_data = 1; got_data;)
    {
        ret = avcodec_encode_audio2(cdc_ctx, pkt, NULL, &got_data);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }

        if (got_data) {
            int nwrite = fwrite(pkt->data, 1, pkt->size, fp_out);
            fprintf(stdout, "nwrite %d data.\n", nwrite);
            av_packet_unref(pkt);
        }

    }

    fclose(fp_out);
    fclose(fp_in);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    avcodec_close(cdc_ctx);
    avcodec_free_context(&cdc_ctx);
    return;
ret7:
    fclose(fp_out);
ret6:
    fclose(fp_in);
ret5:
    av_frame_free(&frame);
ret4:
    av_packet_free(&pkt);
ret3:
    avcodec_close(cdc_ctx);
ret2:
    avcodec_free_context(&cdc_ctx);
ret1:
    exit(1);
}

int main(int argc, const char *argv[])
{

    encode_audio("/home/lili/Videos/short_mixed_stereo_48.pcm", "/home/lili/Videos/output.aac");

    return 0;
}

 

你可能感兴趣的:(ffmpeg入门)