SDL only supports s16 sample format and a limited number of channel layouts. Some versions of SDL on some systems support 4-channel and 6-channel output, but it's safer overall to downmix any layout with more than 2 channels to stereo.
Unified · Split
| @@ -34,7 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "libavformat/avformat.h" |
| 35 | 35 | #include "libavdevice/avdevice.h" |
| 36 | 36 | #include "libswscale/swscale.h" |
| 37 | −#include "libavcodec/audioconvert.h" | |
| 37 | +#include "libavresample/avresample.h" | |
| 38 | 38 | #include "libavutil/opt.h" |
| 39 | 39 | #include "libavcodec/avfft.h" |
| 40 | 40 | |
| @@ -159,8 +159,12 @@ typedef struct VideoState { · 118 unmodified lines | ||
| 159 | 159 | int audio_buf_index; /* in bytes */ |
| 160 | 160 | AVPacket audio_pkt_temp; |
| 161 | 161 | AVPacket audio_pkt; |
| 162 | − enum AVSampleFormat audio_src_fmt; | |
| 163 | − AVAudioConvert *reformat_ctx; | |
| 162 | + enum AVSampleFormat sdl_sample_fmt; | |
| 163 | + uint64_t sdl_channel_layout; | |
| 164 | + int sdl_channels; | |
| 165 | + enum AVSampleFormat resample_sample_fmt; | |
| 166 | + uint64_t resample_channel_layout; | |
| 167 | + AVAudioResampleContext *avr; | |
| 164 | 168 | AVFrame *frame; |
| 165 | 169 | |
| 166 | 170 | int show_audio; /* if true, display audio samples */ |
| @@ -743,7 +747,7 @@ static void video_audio_display(VideoState *s) · 576 unmodified lines | ||
| 743 | 747 | nb_freq = 1 << (rdft_bits - 1); |
| 744 | 748 | |
| 745 | 749 | /* compute display index : center on currently output samples */ |
| 746 | − channels = s->audio_st->codec->channels; | |
| 750 | + channels = s->sdl_channels; | |
| 747 | 751 | nb_display_channels = channels; |
| 748 | 752 | if (!s->paused) { |
| 749 | 753 | int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq); |
| @@ -957,8 +961,8 @@ static double get_audio_clock(VideoState *is) · 207 unmodified lines | ||
| 957 | 961 | hw_buf_size = audio_write_get_buf_size(is); |
| 958 | 962 | bytes_per_sec = 0; |
| 959 | 963 | if (is->audio_st) { |
| 960 | − bytes_per_sec = is->audio_st->codec->sample_rate * | |
| 961 | − 2 * is->audio_st->codec->channels; | |
| 964 | + bytes_per_sec = is->audio_st->codec->sample_rate * is->sdl_channels * | |
| 965 | + av_get_bytes_per_sample(is->sdl_sample_fmt); | |
| 962 | 966 | } |
| 963 | 967 | if (bytes_per_sec) |
| 964 | 968 | pts -= (double)hw_buf_size / bytes_per_sec; |
| @@ -1937,7 +1941,7 @@ static int synchronize_audio(VideoState *is, short *samples, · 972 unmodified lines | ||
| 1937 | 1941 | int n, samples_size; |
| 1938 | 1942 | double ref_clock; |
| 1939 | 1943 | |
| 1940 | − n = 2 * is->audio_st->codec->channels; | |
| 1944 | + n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); | |
| 1941 | 1945 | samples_size = samples_size1; |
| 1942 | 1946 | |
| 1943 | 1947 | /* if not master, then we try to remove or add samples to correct the clock */ |
| @@ -2018,6 +2022,8 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) · 74 unmodified lines | ||
| 2018 | 2022 | for (;;) { |
| 2019 | 2023 | /* NOTE: the audio packet can contain several frames */ |
| 2020 | 2024 | while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) { |
| 2025 | + int resample_changed, audio_resample; | |
| 2026 | + | |
| 2021 | 2027 | if (!is->frame) { |
| 2022 | 2028 | if (!(is->frame = avcodec_alloc_frame())) |
| 2023 | 2029 | return AVERROR(ENOMEM); |
| @@ -2047,39 +2053,67 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) · 23 unmodified lines | ||
| 2047 | 2053 | is->frame->nb_samples, |
| 2048 | 2054 | dec->sample_fmt, 1); |
| 2049 | 2055 | |
| 2050 | − if (dec->sample_fmt != is->audio_src_fmt) { | |
| 2051 | − if (is->reformat_ctx) | |
| 2052 | − av_audio_convert_free(is->reformat_ctx); | |
| 2053 | − is->reformat_ctx= av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, | |
| 2054 | − dec->sample_fmt, 1, NULL, 0); | |
| 2055 | − if (!is->reformat_ctx) { | |
| 2056 | − fprintf(stderr, "Cannot convert %s sample format to %s sample format\n", | |
| 2057 | − av_get_sample_fmt_name(dec->sample_fmt), | |
| 2058 | − av_get_sample_fmt_name(AV_SAMPLE_FMT_S16)); | |
| 2056 | + audio_resample = dec->sample_fmt != is->sdl_sample_fmt || | |
| 2057 | + dec->channel_layout != is->sdl_channel_layout; | |
| 2058 | + | |
| 2059 | + resample_changed = dec->sample_fmt != is->resample_sample_fmt || | |
| 2060 | + dec->channel_layout != is->resample_channel_layout; | |
| 2061 | + | |
| 2062 | + if ((!is->avr && audio_resample) || resample_changed) { | |
| 2063 | + if (is->avr) | |
| 2064 | + avresample_close(is->avr); | |
| 2065 | + else if (audio_resample) { | |
| 2066 | + int ret; | |
| 2067 | + is->avr = avresample_alloc_context(); | |
| 2068 | + if (!is->avr) { | |
| 2069 | + fprintf(stderr, "error allocating AVAudioResampleContext\n"); | |
| 2059 | 2070 | break; |
| 2071 | + } | |
| 2072 | + av_opt_set_int(is->avr, "in_channel_layout", dec->channel_layout, 0); | |
| 2073 | + av_opt_set_int(is->avr, "in_sample_fmt", dec->sample_fmt, 0); | |
| 2074 | + av_opt_set_int(is->avr, "in_sample_rate", dec->sample_rate, 0); | |
| 2075 | + av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0); | |
| 2076 | + av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0); | |
| 2077 | + av_opt_set_int(is->avr, "out_sample_rate", dec->sample_rate, 0); | |
| 2078 | + if (av_get_bytes_per_sample(dec->sample_fmt) <= 2) | |
| 2079 | + av_opt_set_int(is->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0); | |
| 2080 | + | |
| 2081 | + if ((ret = avresample_open(is->avr)) < 0) { | |
| 2082 | + fprintf(stderr, "error initializing libavresample\n"); | |
| 2083 | + break; | |
| 2084 | + } | |
| 2060 | 2085 | } |
| 2061 | − is->audio_src_fmt= dec->sample_fmt; | |
| 2086 | + is->resample_sample_fmt = dec->sample_fmt; | |
| 2087 | + is->resample_channel_layout = dec->channel_layout; | |
| 2062 | 2088 | } |
| 2063 | 2089 | |
| 2064 | − if (is->reformat_ctx) { | |
| 2065 | − const void *ibuf[6] = { is->frame->data[0] }; | |
| 2066 | − void *obuf[6]; | |
| 2067 | − int istride[6] = { av_get_bytes_per_sample(dec->sample_fmt) }; | |
| 2068 | − int ostride[6] = { 2 }; | |
| 2069 | − int len= data_size/istride[0]; | |
| 2070 | − obuf[0] = av_realloc(is->audio_buf1, FFALIGN(len * ostride[0], 32)); | |
| 2071 | − if (!obuf[0]) { | |
| 2090 | + if (audio_resample) { | |
| 2091 | + void *tmp_out; | |
| 2092 | + int out_samples, out_size, out_linesize; | |
| 2093 | + int osize = av_get_bytes_per_sample(is->sdl_sample_fmt); | |
| 2094 | + int nb_samples = is->frame->nb_samples; | |
| 2095 | + | |
| 2096 | + out_size = av_samples_get_buffer_size(&out_linesize, | |
| 2097 | + is->sdl_channels, | |
| 2098 | + nb_samples, | |
| 2099 | + is->sdl_sample_fmt, 0); | |
| 2100 | + tmp_out = av_realloc(is->audio_buf1, out_size); | |
| 2101 | + if (!tmp_out) | |
| 2072 | 2102 | return AVERROR(ENOMEM); |
| 2073 | − } | |
| 2074 | − is->audio_buf1 = obuf[0]; | |
| 2075 | − if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len) < 0) { | |
| 2076 | − printf("av_audio_convert() failed\n"); | |
| 2103 | + is->audio_buf1 = tmp_out; | |
| 2104 | + | |
| 2105 | + out_samples = avresample_convert(is->avr, | |
| 2106 | + (void **)&is->audio_buf1, | |
| 2107 | + out_linesize, nb_samples, | |
| 2108 | + (void **)is->frame->data, | |
| 2109 | + is->frame->linesize[0], | |
| 2110 | + is->frame->nb_samples); | |
| 2111 | + if (out_samples < 0) { | |
| 2112 | + fprintf(stderr, "avresample_convert() failed\n"); | |
| 2077 | 2113 | break; |
| 2078 | 2114 | } |
| 2079 | 2115 | is->audio_buf = is->audio_buf1; |
| 2080 | − /* FIXME: existing code assume that data_size equals framesize*channels*2 | |
| 2081 | − remove this legacy cruft */ | |
| 2082 | − data_size = len * 2; | |
| 2116 | + data_size = out_samples * osize * is->sdl_channels; | |
| 2083 | 2117 | } else { |
| 2084 | 2118 | is->audio_buf = is->frame->data[0]; |
| 2085 | 2119 | } |
| @@ -2087,7 +2121,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) · 1 unmodified line | ||
| 2087 | 2121 | /* if no pts, then compute it */ |
| 2088 | 2122 | pts = is->audio_clock; |
| 2089 | 2123 | *pts_ptr = pts; |
| 2090 | − n = 2 * dec->channels; | |
| 2124 | + n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); | |
| 2091 | 2125 | is->audio_clock += (double)data_size / |
| 2092 | 2126 | (double)(n * dec->sample_rate); |
| 2093 | 2127 | #ifdef DEBUG |
| @@ -2206,7 +2240,20 @@ static int stream_component_open(VideoState *is, int stream_index) · 112 unmodified lines | ||
| 2206 | 2240 | if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { |
| 2207 | 2241 | wanted_spec.freq = avctx->sample_rate; |
| 2208 | 2242 | wanted_spec.format = AUDIO_S16SYS; |
| 2209 | − wanted_spec.channels = avctx->channels; | |
| 2243 | + | |
| 2244 | + if (!avctx->channel_layout) | |
| 2245 | + avctx->channel_layout = av_get_default_channel_layout(avctx->channels); | |
| 2246 | + if (!avctx->channel_layout) { | |
| 2247 | + fprintf(stderr, "unable to guess channel layout\n"); | |
| 2248 | + return -1; | |
| 2249 | + } | |
| 2250 | + if (avctx->channels == 1) | |
| 2251 | + is->sdl_channel_layout = AV_CH_LAYOUT_MONO; | |
| 2252 | + else | |
| 2253 | + is->sdl_channel_layout = AV_CH_LAYOUT_STEREO; | |
| 2254 | + is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout); | |
| 2255 | + | |
| 2256 | + wanted_spec.channels = is->sdl_channels; | |
| 2210 | 2257 | wanted_spec.silence = 0; |
| 2211 | 2258 | wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; |
| 2212 | 2259 | wanted_spec.callback = sdl_audio_callback; |
| @@ -2216,7 +2263,9 @@ static int stream_component_open(VideoState *is, int stream_index) · 3 unmodified lines | ||
| 2216 | 2263 | return -1; |
| 2217 | 2264 | } |
| 2218 | 2265 | is->audio_hw_buf_size = spec.size; |
| 2219 | − is->audio_src_fmt = AV_SAMPLE_FMT_S16; | |
| 2266 | + is->sdl_sample_fmt = AV_SAMPLE_FMT_S16; | |
| 2267 | + is->resample_sample_fmt = is->sdl_sample_fmt; | |
| 2268 | + is->resample_channel_layout = is->sdl_channel_layout; | |
| 2220 | 2269 | } |
| 2221 | 2270 | |
| 2222 | 2271 | ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; |
| @@ -2275,9 +2324,8 @@ static void stream_component_close(VideoState *is, int stream_index) · 52 unmodified lines | ||
| 2275 | 2324 | |
| 2276 | 2325 | packet_queue_end(&is->audioq); |
| 2277 | 2326 | av_free_packet(&is->audio_pkt); |
| 2278 | − if (is->reformat_ctx) | |
| 2279 | − av_audio_convert_free(is->reformat_ctx); | |
| 2280 | − is->reformat_ctx = NULL; | |
| 2327 | + if (is->avr) | |
| 2328 | + avresample_free(&is->avr); | |
| 2281 | 2329 | av_freep(&is->audio_buf1); |
| 2282 | 2330 | is->audio_buf = NULL; |
| 2283 | 2331 | av_freep(&is->frame); |