mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-03-23 04:24:35 +02:00
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.
This commit is contained in:
parent
064f19f39e
commit
40aaa8dadf
2
configure
vendored
2
configure
vendored
@ -1210,6 +1210,7 @@ COMPONENT_LIST="
|
|||||||
|
|
||||||
EXAMPLE_LIST="
|
EXAMPLE_LIST="
|
||||||
avcodec_example
|
avcodec_example
|
||||||
|
encode_audio_example
|
||||||
filter_audio_example
|
filter_audio_example
|
||||||
metadata_example
|
metadata_example
|
||||||
output_example
|
output_example
|
||||||
@ -2435,6 +2436,7 @@ scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer"
|
|||||||
|
|
||||||
# examples
|
# examples
|
||||||
avcodec_example_deps="avcodec avutil"
|
avcodec_example_deps="avcodec avutil"
|
||||||
|
encode_audio_example_deps="avcodec avutil"
|
||||||
filter_audio_example_deps="avfilter avutil"
|
filter_audio_example_deps="avfilter avutil"
|
||||||
metadata_example_deps="avformat avutil"
|
metadata_example_deps="avformat avutil"
|
||||||
output_example_deps="avcodec avformat avutil swscale"
|
output_example_deps="avcodec avformat avutil swscale"
|
||||||
|
@ -17,12 +17,13 @@ DOCS-$(CONFIG_TEXI2HTML) += $(HTMLPAGES)
|
|||||||
DOCS = $(DOCS-yes)
|
DOCS = $(DOCS-yes)
|
||||||
|
|
||||||
DOC_EXAMPLES-$(CONFIG_AVCODEC_EXAMPLE) += avcodec
|
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_FILTER_AUDIO_EXAMPLE) += filter_audio
|
||||||
DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata
|
DOC_EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata
|
||||||
DOC_EXAMPLES-$(CONFIG_OUTPUT_EXAMPLE) += output
|
DOC_EXAMPLES-$(CONFIG_OUTPUT_EXAMPLE) += output
|
||||||
DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec
|
DOC_EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec
|
||||||
DOC_EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac
|
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))
|
DOC_EXAMPLES := $(DOC_EXAMPLES-yes:%=doc/examples/%$(EXESUF))
|
||||||
ALL_DOC_EXAMPLES := $(ALL_DOC_EXAMPLES:%=doc/examples/%$(EXESUF))
|
ALL_DOC_EXAMPLES := $(ALL_DOC_EXAMPLES:%=doc/examples/%$(EXESUF))
|
||||||
|
@ -47,175 +47,6 @@
|
|||||||
#define AUDIO_INBUF_SIZE 20480
|
#define AUDIO_INBUF_SIZE 20480
|
||||||
#define AUDIO_REFILL_THRESH 4096
|
#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.
|
* Audio decoding.
|
||||||
*/
|
*/
|
||||||
@ -575,7 +406,6 @@ int main(int argc, char **argv)
|
|||||||
avcodec_register_all();
|
avcodec_register_all();
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
audio_encode_example("/tmp/test.mp2");
|
|
||||||
audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
|
audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
|
||||||
|
|
||||||
video_encode_example("/tmp/test.mpg");
|
video_encode_example("/tmp/test.mpg");
|
||||||
|
211
doc/examples/encode_audio.c
Normal file
211
doc/examples/encode_audio.c
Normal file
@ -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 <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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 <output file>\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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user