From e0d2714adc4985198a4c9fadf76508cfe7c131d0 Mon Sep 17 00:00:00 2001 From: Juanjo Date: Tue, 9 Apr 2002 04:52:49 +0000 Subject: [PATCH] - Fixed AC3 decoding for 5:1 AC3 streams. Now when calling av_audio_decode for AC3 set avcodec_context->channels to the desired number channels, if the setting is 0 AC3 decoder will set it to the channels found in the stream. - Changed ffmpeg to cope with the new "way" of AC3 decoding. - ASF muxer now uses Tickers for PTS calculations. Originally committed as revision 393 to svn://svn.ffmpeg.org/ffmpeg/trunk --- ffmpeg.c | 21 ++++++++++++++++++--- libav/asf.c | 22 +++++++++++++++++----- libavcodec/ac3dec.c | 29 +++++++++++++++-------------- libavcodec/utils.c | 18 +++++++++++++++++- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index da084de121..2c18cd852d 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -741,10 +741,19 @@ static int av_encode(AVFormatContext **output_files, codec->sample_rate == icodec->sample_rate) { ost->audio_resample = 0; } else { - ost->audio_resample = 1; - ost->resample = audio_resample_init(codec->channels, icodec->channels, + if (codec->channels != icodec->channels && + icodec->codec_id == CODEC_ID_AC3) { + /* Special case for 5:1 AC3 input */ + /* and mono or stereo output */ + ost->audio_resample = 0; + /* Request specific number of channels */ + icodec->channels = codec->channels; + } else { + ost->audio_resample = 1; + ost->resample = audio_resample_init(codec->channels, icodec->channels, codec->sample_rate, icodec->sample_rate); + } } ist->decoding_needed = 1; ost->encoding_needed = 1; @@ -1626,6 +1635,7 @@ void opt_input_file(const char *filename) AVCodecContext *enc = &ic->streams[i]->codec; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: + //fprintf(stderr, "\nInput Audio channels: %d", enc->channels); audio_channels = enc->channels; audio_sample_rate = enc->sample_rate; break; @@ -1789,7 +1799,12 @@ void opt_output_file(const char *filename) audio_enc->bit_rate = audio_bit_rate; audio_enc->sample_rate = audio_sample_rate; - audio_enc->channels = audio_channels; + /* For audio codecs other than AC3 we limit */ + /* the number of coded channels to stereo */ + if (audio_channels > 2 && codec_id != CODEC_ID_AC3) { + audio_enc->channels = 2; + } else + audio_enc->channels = audio_channels; oc->streams[nb_streams] = st; nb_streams++; } diff --git a/libav/asf.c b/libav/asf.c index 90fa685c3f..adc2437ea4 100644 --- a/libav/asf.c +++ b/libav/asf.c @@ -18,6 +18,7 @@ */ #include "avformat.h" #include "avi.h" +#include "tick.h" #define PACKET_SIZE 3200 #define PACKET_HEADER_SIZE 12 @@ -26,6 +27,7 @@ typedef struct { int num; int seq; + Ticker pts_ticker; /* use for reading */ AVPacket pkt; int frag_offset; @@ -283,6 +285,7 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu /* stream headers */ for(n=0;nnb_streams;n++) { + ASFStream *stream = &asf->streams[n]; enc = &s->streams[n]->codec; asf->streams[n].num = n + 1; asf->streams[n].seq = 0; @@ -292,12 +295,20 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu wav_extra_size = 0; extra_size = 18 + wav_extra_size; extra_size2 = 0; + /* Init the ticker */ + ticker_init(&stream->pts_ticker, + enc->sample_rate, + 1000 * enc->frame_size); break; default: case CODEC_TYPE_VIDEO: wav_extra_size = 0; extra_size = 0x33; extra_size2 = 0; + /* Init the ticker */ + ticker_init(&stream->pts_ticker, + enc->frame_rate, + 1000 * FRAME_RATE_BASE); break; } @@ -543,26 +554,27 @@ static int asf_write_packet(AVFormatContext *s, int stream_index, UINT8 *buf, int size, int force_pts) { ASFContext *asf = s->priv_data; + ASFStream *stream; int timestamp; INT64 duration; AVCodecContext *codec; codec = &s->streams[stream_index]->codec; + stream = &asf->streams[stream_index]; + if (codec->codec_type == CODEC_TYPE_AUDIO) { - timestamp = (int)((float)codec->frame_number * codec->frame_size * 1000.0 / - codec->sample_rate); + timestamp = (int)ticker_tick(&stream->pts_ticker, codec->frame_number); duration = (codec->frame_number * codec->frame_size * INT64_C(10000000)) / codec->sample_rate; } else { - timestamp = (int)((float)codec->frame_number * 1000.0 * FRAME_RATE_BASE / - codec->frame_rate); + timestamp = (int)ticker_tick(&stream->pts_ticker, codec->frame_number); duration = codec->frame_number * ((INT64_C(10000000) * FRAME_RATE_BASE) / codec->frame_rate); } if (duration > asf->duration) asf->duration = duration; - put_frame(s, &asf->streams[stream_index], (int)timestamp, buf, size); + put_frame(s, stream, timestamp, buf, size); return 0; } diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index c0d801da2d..eade4fb6ae 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -108,13 +108,16 @@ static int ac3_decode_frame(AVCodecContext *avctx, /* update codec info */ avctx->sample_rate = sample_rate; s->channels = ac3_channels[s->flags & 7]; - if (s->flags & AC3_LFE) - s->channels++; - if (s->channels < avctx->channels) { - fprintf(stderr, "Source channels are less than specified: output to %d channels..\n", s->channels); - avctx->channels = s->channels; - } - avctx->bit_rate = bit_rate; + if (s->flags & AC3_LFE) + s->channels++; + if (avctx->channels == 0) + /* No specific number of channel requested */ + avctx->channels = s->channels; + else if (s->channels < avctx->channels) { + fprintf(stderr, "libav: AC3 Source channels are less than specified: output to %d channels..\n", s->channels); + avctx->channels = s->channels; + } + avctx->bit_rate = bit_rate; } } } else if (len < s->frame_size) { @@ -127,15 +130,13 @@ static int ac3_decode_frame(AVCodecContext *avctx, s->inbuf_ptr += len; buf_size -= len; } else { -#if 0 + flags = s->flags; if (avctx->channels == 1) flags = AC3_MONO; - else + else if (avctx->channels == 2) flags = AC3_STEREO; -#else - flags = s->flags; -#endif - flags |= AC3_ADJUST_LEVEL; + else + flags |= AC3_ADJUST_LEVEL; level = 1; if (ac3_frame (&s->state, s->inbuf, &flags, &level, 384)) { fail: @@ -146,7 +147,7 @@ static int ac3_decode_frame(AVCodecContext *avctx, for (i = 0; i < 6; i++) { if (ac3_block (&s->state)) goto fail; - float_to_int (*samples, out_samples + i * 256 * avctx->channels, avctx->channels); + float_to_int (*samples, out_samples + i * 256 * avctx->channels, avctx->channels); } s->inbuf_ptr = s->inbuf; s->frame_size = 0; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 815d215757..e74926841a 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -219,6 +219,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) const char *codec_name; AVCodec *p; char buf1[32]; + char *channels_str=NULL; int bitrate; if (encode) @@ -269,12 +270,27 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) snprintf(buf, buf_size, "Audio: %s", codec_name); + switch (enc->channels) { + case 1: + channels_str = "mono"; + break; + case 2: + channels_str = "stereo"; + break; + case 6: + channels_str = "5:1"; + break; + default: + sprintf(channels_str, "%d channels", enc->channels); + break; + } if (enc->sample_rate) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %d Hz, %s", enc->sample_rate, - enc->channels == 2 ? "stereo" : "mono"); + channels_str); } + /* for PCM codecs, compute bitrate directly */ switch(enc->codec_id) { case CODEC_ID_PCM_S16LE: