FFmpeg
swresample_frame.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Luca Barbato <lu_zero@gentoo.org>
3  * Copyright (c) 2014 Michael Niedermayer <michaelni@gmx.at>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "swresample_internal.h"
23 #include "libavutil/frame.h"
24 #include "libavutil/opt.h"
25 
27 {
28  swr_close(s);
29 
30  if (in) {
31  if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 0)
32  goto fail;
33  if (av_opt_set_int(s, "isf", in->format, 0) < 0)
34  goto fail;
35  if (av_opt_set_int(s, "isr", in->sample_rate, 0) < 0)
36  goto fail;
37  }
38 
39  if (out) {
40  if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 0)
41  goto fail;
42  if (av_opt_set_int(s, "osf", out->format, 0) < 0)
43  goto fail;
44  if (av_opt_set_int(s, "osr", out->sample_rate, 0) < 0)
45  goto fail;
46  }
47 
48  return 0;
49 fail:
50  av_log(s, AV_LOG_ERROR, "Failed to set option\n");
51  return AVERROR(EINVAL);
52 }
53 
55  const AVFrame *out, const AVFrame *in)
56 {
57  int ret = 0;
58 
59  if (in) {
60  if (s->in_ch_layout != in->channel_layout ||
61  s->in_sample_rate != in->sample_rate ||
62  s->in_sample_fmt != in->format) {
63  ret |= AVERROR_INPUT_CHANGED;
64  }
65  }
66 
67  if (out) {
68  if (s->out_ch_layout != out->channel_layout ||
69  s->out_sample_rate != out->sample_rate ||
70  s->out_sample_fmt != out->format) {
72  }
73  }
74 
75  return ret;
76 }
77 
78 static inline int convert_frame(SwrContext *s,
79  AVFrame *out, const AVFrame *in)
80 {
81  int ret;
82  uint8_t **out_data = NULL;
83  const uint8_t **in_data = NULL;
84  int out_nb_samples = 0, in_nb_samples = 0;
85 
86  if (out) {
87  out_data = out->extended_data;
88  out_nb_samples = out->nb_samples;
89  }
90 
91  if (in) {
92  in_data = (const uint8_t **)in->extended_data;
93  in_nb_samples = in->nb_samples;
94  }
95 
96  ret = swr_convert(s, out_data, out_nb_samples, in_data, in_nb_samples);
97 
98  if (ret < 0) {
99  if (out)
100  out->nb_samples = 0;
101  return ret;
102  }
103 
104  if (out)
105  out->nb_samples = ret;
106 
107  return 0;
108 }
109 
110 static inline int available_samples(AVFrame *out)
111 {
112  int bytes_per_sample = av_get_bytes_per_sample(out->format);
113  int samples = out->linesize[0] / bytes_per_sample;
114 
115  if (av_sample_fmt_is_planar(out->format)) {
116  return samples;
117  } else {
119  return samples / channels;
120  }
121 }
122 
124  AVFrame *out, const AVFrame *in)
125 {
126  int ret, setup = 0;
127 
128  if (!swr_is_initialized(s)) {
129  if ((ret = swr_config_frame(s, out, in)) < 0)
130  return ret;
131  if ((ret = swr_init(s)) < 0)
132  return ret;
133  setup = 1;
134  } else {
135  // return as is or reconfigure for input changes?
136  if ((ret = config_changed(s, out, in)))
137  return ret;
138  }
139 
140  if (out) {
141  if (!out->linesize[0]) {
142  out->nb_samples = swr_get_delay(s, s->out_sample_rate) + 3;
143  if (in) {
144  out->nb_samples += in->nb_samples*(int64_t)s->out_sample_rate / s->in_sample_rate;
145  }
146  if ((ret = av_frame_get_buffer(out, 0)) < 0) {
147  if (setup)
148  swr_close(s);
149  return ret;
150  }
151  } else {
152  if (!out->nb_samples)
153  out->nb_samples = available_samples(out);
154  }
155  }
156 
157  return convert_frame(s, out, in);
158 }
159 
#define NULL
Definition: coverity.c:32
av_cold void swr_close(SwrContext *s)
Closes the context so that swr_is_initialized() returns 0.
Definition: swresample.c:148
int out_sample_rate
output sample rate
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
channels
Definition: aptx.c:30
static int config_changed(SwrContext *s, const AVFrame *out, const AVFrame *in)
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
uint8_t
AVOptions.
enum AVSampleFormat out_sample_fmt
output sample format
#define av_log(a,...)
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:112
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
The libswresample context.
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:568
int64_t swr_get_delay(struct SwrContext *s, int64_t base)
Gets the delay the next input sample will experience relative to the next output sample.
Definition: swresample.c:867
#define fail()
Definition: checkasm.h:121
reference-counted frame API
uint64_t channel_layout
Channel layout of the audio data.
Definition: frame.h:472
static int convert_frame(SwrContext *s, AVFrame *out, const AVFrame *in)
int64_t out_ch_layout
output channel layout
#define AVERROR_INPUT_CHANGED
Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) ...
Definition: error.h:73
int in_sample_rate
input sample rate
#define s(width, name)
Definition: cbs_vp9.c:257
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
int sample_rate
Sample rate of the audio data.
Definition: frame.h:467
enum AVSampleFormat in_sample_fmt
input sample format
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, const uint8_t *in_arg[SWR_CH_MAX], int in_count)
Definition: swresample.c:714
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:324
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
#define AVERROR_OUTPUT_CHANGED
Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) ...
Definition: error.h:74
int64_t in_ch_layout
input channel layout
int swr_convert_frame(SwrContext *s, AVFrame *out, const AVFrame *in)
Convert the samples in the input AVFrame and write them to the output AVFrame.
static int available_samples(AVFrame *out)
int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in)
Configure or reconfigure the SwrContext using the information provided by the AVFrames.
FILE * out
Definition: movenc.c:54
Filter the word “frame” indicates either a video frame or a group of audio samples
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:342
int swr_is_initialized(struct SwrContext *s)
Check whether an swr context has been initialized or not.
Definition: swresample.c:710
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:361
av_cold int swr_init(struct SwrContext *s)
Initialize context after user parameters have been set.
Definition: swresample.c:152