From 40aaa8dadfd1c69ff4460d04750e1403b5535a6d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 19 Oct 2016 21:05:22 +0200 Subject: [PATCH] examples/avcodec: split audio encoding into a separate example The four examples (audio/video encoding/decoding) are completely independent so it makes little sense to have them all in one file. --- configure | 2 + doc/Makefile | 3 +- doc/examples/avcodec.c | 170 ----------------------------- doc/examples/encode_audio.c | 211 ++++++++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 171 deletions(-) create mode 100644 doc/examples/encode_audio.c diff --git a/configure b/configure index 8c2b4fdfa9..28567bb7df 100755 --- a/configure +++ b/configure @@ -1210,6 +1210,7 @@ COMPONENT_LIST=" EXAMPLE_LIST=" avcodec_example + encode_audio_example filter_audio_example metadata_example output_example @@ -2435,6 +2436,7 @@ scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer" # examples avcodec_example_deps="avcodec avutil" +encode_audio_example_deps="avcodec avutil" filter_audio_example_deps="avfilter avutil" metadata_example_deps="avformat avutil" output_example_deps="avcodec avformat avutil swscale" diff --git a/doc/Makefile b/doc/Makefile index c464a4869e..738e601109 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -17,12 +17,13 @@ DOCS-$(CONFIG_TEXI2HTML) += $(HTMLPAGES) DOCS = $(DOCS-yes) DOC_EXAMPLES-$(CONFIG_AVCODEC_EXAMPLE) += avcodec +DOC_EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio DOC_EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata DOC_EXAMPLES-$(CONFIG_OUTPUT_EXAMPLE) += output DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec DOC_EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac -ALL_DOC_EXAMPLES = avcodec filter_audio metadata output transcode_aac +ALL_DOC_EXAMPLES = avcodec encode_audio filter_audio metadata output transcode_aac DOC_EXAMPLES := $(DOC_EXAMPLES-yes:%=doc/examples/%$(EXESUF)) ALL_DOC_EXAMPLES := $(ALL_DOC_EXAMPLES:%=doc/examples/%$(EXESUF)) diff --git a/doc/examples/avcodec.c b/doc/examples/avcodec.c index 8fee5526df..63812d99c3 100644 --- a/doc/examples/avcodec.c +++ b/doc/examples/avcodec.c @@ -47,175 +47,6 @@ #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 -/* check that a given sample format is supported by the encoder */ -static int check_sample_fmt(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(AVCodec *codec) -{ - const int *p; - int best_samplerate = 0; - - if (!codec->supported_samplerates) - return 44100; - - p = codec->supported_samplerates; - while (*p) { - best_samplerate = FFMAX(*p, best_samplerate); - p++; - } - return best_samplerate; -} - -/* select layout with the highest channel count */ -static int select_channel_layout(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; -} - -/* - * Audio encoding example - */ -static void audio_encode_example(const char *filename) -{ - AVCodec *codec; - AVCodecContext *c= NULL; - AVFrame *frame; - AVPacket pkt; - int i, j, k, ret, got_output; - int buffer_size; - FILE *f; - uint16_t *samples; - float t, tincr; - - printf("Audio encoding\n"); - - /* find the MP2 encoder */ - codec = avcodec_find_encoder(AV_CODEC_ID_MP2); - if (!codec) { - fprintf(stderr, "codec not found\n"); - exit(1); - } - - c = avcodec_alloc_context3(codec); - - /* put sample parameters */ - c->bit_rate = 64000; - - /* check that the encoder supports s16 pcm input */ - c->sample_fmt = AV_SAMPLE_FMT_S16; - if (!check_sample_fmt(codec, c->sample_fmt)) { - fprintf(stderr, "encoder does not support %s", - av_get_sample_fmt_name(c->sample_fmt)); - exit(1); - } - - /* select other audio parameters supported by the encoder */ - c->sample_rate = select_sample_rate(codec); - c->channel_layout = select_channel_layout(codec); - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); - - /* open it */ - if (avcodec_open2(c, codec, NULL) < 0) { - fprintf(stderr, "could not open codec\n"); - exit(1); - } - - f = fopen(filename, "wb"); - if (!f) { - fprintf(stderr, "could not open %s\n", filename); - exit(1); - } - - /* frame containing input raw audio */ - frame = av_frame_alloc(); - if (!frame) { - fprintf(stderr, "could not allocate audio frame\n"); - exit(1); - } - - frame->nb_samples = c->frame_size; - frame->format = c->sample_fmt; - frame->channel_layout = c->channel_layout; - - /* the codec gives us the frame size, in samples, - * we calculate the size of the samples buffer in bytes */ - buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, - c->sample_fmt, 0); - samples = av_malloc(buffer_size); - if (!samples) { - fprintf(stderr, "could not allocate %d bytes for samples buffer\n", - buffer_size); - exit(1); - } - /* setup the data pointers in the AVFrame */ - ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, - (const uint8_t*)samples, buffer_size, 0); - if (ret < 0) { - fprintf(stderr, "could not setup audio frame\n"); - exit(1); - } - - /* encode a single tone sound */ - t = 0; - tincr = 2 * M_PI * 440.0 / c->sample_rate; - for(i=0;i<200;i++) { - av_init_packet(&pkt); - pkt.data = NULL; // packet data will be allocated by the encoder - pkt.size = 0; - - for (j = 0; j < c->frame_size; j++) { - samples[2*j] = (int)(sin(t) * 10000); - - for (k = 1; k < c->channels; k++) - samples[2*j + k] = samples[2*j]; - t += tincr; - } - /* encode the samples */ - ret = avcodec_encode_audio2(c, &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, f); - av_packet_unref(&pkt); - } - } - fclose(f); - - av_freep(&samples); - av_frame_free(&frame); - avcodec_free_context(&c); -} - /* * Audio decoding. */ @@ -575,7 +406,6 @@ int main(int argc, char **argv) avcodec_register_all(); if (argc <= 1) { - audio_encode_example("/tmp/test.mp2"); audio_decode_example("/tmp/test.sw", "/tmp/test.mp2"); video_encode_example("/tmp/test.mpg"); diff --git a/doc/examples/encode_audio.c b/doc/examples/encode_audio.c new file mode 100644 index 0000000000..cabe5893b0 --- /dev/null +++ b/doc/examples/encode_audio.c @@ -0,0 +1,211 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * audio encoding with libavcodec API example. + * + * @example encode_audio.c + */ + +#include +#include +#include + +#include "libavcodec/avcodec.h" + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +/* check that a given sample format is supported by the encoder */ +static int check_sample_fmt(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(AVCodec *codec) +{ + const int *p; + int best_samplerate = 0; + + if (!codec->supported_samplerates) + return 44100; + + p = codec->supported_samplerates; + while (*p) { + best_samplerate = FFMAX(*p, best_samplerate); + p++; + } + return best_samplerate; +} + +/* select layout with the highest channel count */ +static int select_channel_layout(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(int argc, char **argv) +{ + const char *filename; + AVCodec *codec; + AVCodecContext *c= NULL; + AVFrame *frame; + AVPacket pkt; + int i, j, k, ret, got_output; + int buffer_size; + FILE *f; + uint16_t *samples; + float t, tincr; + + if (argc <= 1) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 0; + } + filename = argv[1]; + + /* register all the codecs */ + avcodec_register_all(); + + /* find the MP2 encoder */ + codec = avcodec_find_encoder(AV_CODEC_ID_MP2); + if (!codec) { + fprintf(stderr, "codec not found\n"); + exit(1); + } + + c = avcodec_alloc_context3(codec); + + /* put sample parameters */ + c->bit_rate = 64000; + + /* check that the encoder supports s16 pcm input */ + c->sample_fmt = AV_SAMPLE_FMT_S16; + if (!check_sample_fmt(codec, c->sample_fmt)) { + fprintf(stderr, "encoder does not support %s", + av_get_sample_fmt_name(c->sample_fmt)); + exit(1); + } + + /* select other audio parameters supported by the encoder */ + c->sample_rate = select_sample_rate(codec); + c->channel_layout = select_channel_layout(codec); + c->channels = av_get_channel_layout_nb_channels(c->channel_layout); + + /* open it */ + if (avcodec_open2(c, codec, NULL) < 0) { + fprintf(stderr, "could not open codec\n"); + exit(1); + } + + f = fopen(filename, "wb"); + if (!f) { + fprintf(stderr, "could not open %s\n", filename); + exit(1); + } + + /* frame containing input raw audio */ + frame = av_frame_alloc(); + if (!frame) { + fprintf(stderr, "could not allocate audio frame\n"); + exit(1); + } + + frame->nb_samples = c->frame_size; + frame->format = c->sample_fmt; + frame->channel_layout = c->channel_layout; + + /* the codec gives us the frame size, in samples, + * we calculate the size of the samples buffer in bytes */ + buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, + c->sample_fmt, 0); + samples = av_malloc(buffer_size); + if (!samples) { + fprintf(stderr, "could not allocate %d bytes for samples buffer\n", + buffer_size); + exit(1); + } + /* setup the data pointers in the AVFrame */ + ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, + (const uint8_t*)samples, buffer_size, 0); + if (ret < 0) { + fprintf(stderr, "could not setup audio frame\n"); + exit(1); + } + + /* encode a single tone sound */ + t = 0; + tincr = 2 * M_PI * 440.0 / c->sample_rate; + for(i=0;i<200;i++) { + av_init_packet(&pkt); + pkt.data = NULL; // packet data will be allocated by the encoder + pkt.size = 0; + + for (j = 0; j < c->frame_size; j++) { + samples[2*j] = (int)(sin(t) * 10000); + + for (k = 1; k < c->channels; k++) + samples[2*j + k] = samples[2*j]; + t += tincr; + } + /* encode the samples */ + ret = avcodec_encode_audio2(c, &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, f); + av_packet_unref(&pkt); + } + } + fclose(f); + + av_freep(&samples); + av_frame_free(&frame); + avcodec_free_context(&c); +}