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 | #include "libavformat/avformat.h" | 34 | #include "libavformat/avformat.h" |
| 35 | #include "libavdevice/avdevice.h" | 35 | #include "libavdevice/avdevice.h" |
| 36 | #include "libswscale/swscale.h" | 36 | #include "libswscale/swscale.h" |
| 37 | #include "libavcodec/audioconvert.h" | 37 | #include "libavresample/avresample.h" |
| 38 | #include "libavutil/opt.h" | 38 | #include "libavutil/opt.h" |
| 39 | #include "libavcodec/avfft.h" | 39 | #include "libavcodec/avfft.h" |
| 40 | 40 | ||
| @@ -159,8 +159,12 @@ typedef struct VideoState { · 118 unmodified lines | |||
| 159 | int audio_buf_index; /* in bytes */ | 159 | int audio_buf_index; /* in bytes */ |
| 160 | AVPacket audio_pkt_temp; | 160 | AVPacket audio_pkt_temp; |
| 161 | AVPacket audio_pkt; | 161 | AVPacket audio_pkt; |
| 162 | enum AVSampleFormat audio_src_fmt; | 162 | enum AVSampleFormat sdl_sample_fmt; |
| 163 | AVAudioConvert *reformat_ctx; | 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 | AVFrame *frame; | 168 | AVFrame *frame; |
| 165 | 169 | ||
| 166 | int show_audio; /* if true, display audio samples */ | 170 | int show_audio; /* if true, display audio samples */ |
| @@ -743,7 +747,7 @@ static void video_audio_display(VideoState *s) · 576 unmodified lines | |||
| 743 | nb_freq = 1 << (rdft_bits - 1); | 747 | nb_freq = 1 << (rdft_bits - 1); |
| 744 | 748 | ||
| 745 | /* compute display index : center on currently output samples */ | 749 | /* compute display index : center on currently output samples */ |
| 746 | channels = s->audio_st->codec->channels; | 750 | channels = s->sdl_channels; |
| 747 | nb_display_channels = channels; | 751 | nb_display_channels = channels; |
| 748 | if (!s->paused) { | 752 | if (!s->paused) { |
| 749 | int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq); | 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 | hw_buf_size = audio_write_get_buf_size(is); | 961 | hw_buf_size = audio_write_get_buf_size(is); |
| 958 | bytes_per_sec = 0; | 962 | bytes_per_sec = 0; |
| 959 | if (is->audio_st) { | 963 | if (is->audio_st) { |
| 960 | bytes_per_sec = is->audio_st->codec->sample_rate * | 964 | bytes_per_sec = is->audio_st->codec->sample_rate * is->sdl_channels * |
| 961 | 2 * is->audio_st->codec->channels; | 965 | av_get_bytes_per_sample(is->sdl_sample_fmt); |
| 962 | } | 966 | } |
| 963 | if (bytes_per_sec) | 967 | if (bytes_per_sec) |
| 964 | pts -= (double)hw_buf_size / bytes_per_sec; | 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 | int n, samples_size; | 1941 | int n, samples_size; |
| 1938 | double ref_clock; | 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 | samples_size = samples_size1; | 1945 | samples_size = samples_size1; |
| 1942 | 1946 | ||
| 1943 | /* if not master, then we try to remove or add samples to correct the clock */ | 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 | for (;;) { | 2022 | for (;;) { |
| 2019 | /* NOTE: the audio packet can contain several frames */ | 2023 | /* NOTE: the audio packet can contain several frames */ |
| 2020 | while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) { | 2024 | while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) { |
| 2025 | int resample_changed, audio_resample; | ||
| 2026 | |||
| 2021 | if (!is->frame) { | 2027 | if (!is->frame) { |
| 2022 | if (!(is->frame = avcodec_alloc_frame())) | 2028 | if (!(is->frame = avcodec_alloc_frame())) |
| 2023 | return AVERROR(ENOMEM); | 2029 | return AVERROR(ENOMEM); |
| @@ -2047,39 +2053,67 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) · 23 unmodified lines | |||
| 2047 | is->frame->nb_samples, | 2053 | is->frame->nb_samples, |
| 2048 | dec->sample_fmt, 1); | 2054 | dec->sample_fmt, 1); |
| 2049 | 2055 | ||
| 2050 | if (dec->sample_fmt != is->audio_src_fmt) { | 2056 | audio_resample = dec->sample_fmt != is->sdl_sample_fmt || |
| 2051 | if (is->reformat_ctx) | 2057 | dec->channel_layout != is->sdl_channel_layout; |
| 2052 | av_audio_convert_free(is->reformat_ctx); | 2058 | |
| 2053 | is->reformat_ctx= av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, | 2059 | resample_changed = dec->sample_fmt != is->resample_sample_fmt || |
| 2054 | dec->sample_fmt, 1, NULL, 0); | 2060 | dec->channel_layout != is->resample_channel_layout; |
| 2055 | if (!is->reformat_ctx) { | 2061 | |
| 2056 | fprintf(stderr, "Cannot convert %s sample format to %s sample format\n", | 2062 | if ((!is->avr && audio_resample) || resample_changed) { |
| 2057 | av_get_sample_fmt_name(dec->sample_fmt), | 2063 | if (is->avr) |
| 2058 | av_get_sample_fmt_name(AV_SAMPLE_FMT_S16)); | 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 | break; | 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) { | 2090 | if (audio_resample) { |
| 2065 | const void *ibuf[6] = { is->frame->data[0] }; | 2091 | void *tmp_out; |
| 2066 | void *obuf[6]; | 2092 | int out_samples, out_size, out_linesize; |
| 2067 | int istride[6] = { av_get_bytes_per_sample(dec->sample_fmt) }; | 2093 | int osize = av_get_bytes_per_sample(is->sdl_sample_fmt); |
| 2068 | int ostride[6] = { 2 }; | 2094 | int nb_samples = is->frame->nb_samples; |
| 2069 | int len= data_size/istride[0]; | 2095 | |
| 2070 | obuf[0] = av_realloc(is->audio_buf1, FFALIGN(len * ostride[0], 32)); | 2096 | out_size = av_samples_get_buffer_size(&out_linesize, |
| 2071 | if (!obuf[0]) { | 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 | return AVERROR(ENOMEM); | 2102 | return AVERROR(ENOMEM); |
| 2073 | } | 2103 | is->audio_buf1 = tmp_out; |
| 2074 | is->audio_buf1 = obuf[0]; | 2104 | |
| 2075 | if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len) < 0) { | 2105 | out_samples = avresample_convert(is->avr, |
| 2076 | printf("av_audio_convert() failed\n"); | 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 | break; | 2113 | break; |
| 2078 | } | 2114 | } |
| 2079 | is->audio_buf = is->audio_buf1; | 2115 | is->audio_buf = is->audio_buf1; |
| 2080 | /* FIXME: existing code assume that data_size equals framesize*channels*2 | 2116 | data_size = out_samples * osize * is->sdl_channels; |
| 2081 | remove this legacy cruft */ | ||
| 2082 | data_size = len * 2; | ||
| 2083 | } else { | 2117 | } else { |
| 2084 | is->audio_buf = is->frame->data[0]; | 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 | /* if no pts, then compute it */ | 2121 | /* if no pts, then compute it */ |
| 2088 | pts = is->audio_clock; | 2122 | pts = is->audio_clock; |
| 2089 | *pts_ptr = pts; | 2123 | *pts_ptr = pts; |
| 2090 | n = 2 * dec->channels; | 2124 | n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); |
| 2091 | is->audio_clock += (double)data_size / | 2125 | is->audio_clock += (double)data_size / |
| 2092 | (double)(n * dec->sample_rate); | 2126 | (double)(n * dec->sample_rate); |
| 2093 | #ifdef DEBUG | 2127 | #ifdef DEBUG |
| @@ -2206,7 +2240,20 @@ static int stream_component_open(VideoState *is, int stream_index) · 112 unmodified lines | |||
| 2206 | if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { | 2240 | if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { |
| 2207 | wanted_spec.freq = avctx->sample_rate; | 2241 | wanted_spec.freq = avctx->sample_rate; |
| 2208 | wanted_spec.format = AUDIO_S16SYS; | 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 | wanted_spec.silence = 0; | 2257 | wanted_spec.silence = 0; |
| 2211 | wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; | 2258 | wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; |
| 2212 | wanted_spec.callback = sdl_audio_callback; | 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 | return -1; | 2263 | return -1; |
| 2217 | } | 2264 | } |
| 2218 | is->audio_hw_buf_size = spec.size; | 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 | ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; | 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 | packet_queue_end(&is->audioq); | 2325 | packet_queue_end(&is->audioq); |
| 2277 | av_free_packet(&is->audio_pkt); | 2326 | av_free_packet(&is->audio_pkt); |
| 2278 | if (is->reformat_ctx) | 2327 | if (is->avr) |
| 2279 | av_audio_convert_free(is->reformat_ctx); | 2328 | avresample_free(&is->avr); |
| 2280 | is->reformat_ctx = NULL; | ||
| 2281 | av_freep(&is->audio_buf1); | 2329 | av_freep(&is->audio_buf1); |
| 2282 | is->audio_buf = NULL; | 2330 | is->audio_buf = NULL; |
| 2283 | av_freep(&is->frame); | 2331 | av_freep(&is->frame); |