[FFmpeg-soc] [soc]: r1138 - in eac3: ac3dec.c ac3dec.h checkout.sh eac3.h eac3dec.c ffmpeg.patch
bwolowiec
subversion at mplayerhq.hu
Tue Aug 21 22:50:09 CEST 2007
Author: bwolowiec
Date: Tue Aug 21 22:50:09 2007
New Revision: 1138
Log:
adding stereo downmix
Modified:
eac3/ac3dec.c
eac3/ac3dec.h
eac3/checkout.sh
eac3/eac3.h
eac3/eac3dec.c
eac3/ffmpeg.patch
Modified: eac3/ac3dec.c
==============================================================================
--- eac3/ac3dec.c (original)
+++ eac3/ac3dec.c Tue Aug 21 22:50:09 2007
@@ -721,7 +721,7 @@ static inline void do_imdct(AC3DecodeCon
/**
* Downmix the output to mono or stereo.
*/
-static void ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
+void ff_ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
int output_mode, float coef[AC3_MAX_CHANNELS][2])
{
int i, j;
@@ -1041,7 +1041,7 @@ static int ac3_parse_audio_block(AC3Deco
/* downmix output if needed */
if(ctx->nchans != ctx->out_channels && !((ctx->output_mode & AC3_OUTPUT_LFEON) &&
ctx->nfchans == ctx->out_channels)) {
- ac3_downmix(ctx->output, ctx->nfchans, ctx->output_mode,
+ ff_ac3_downmix(ctx->output, ctx->nfchans, ctx->output_mode,
ctx->downmix_coeffs);
}
Modified: eac3/ac3dec.h
==============================================================================
--- eac3/ac3dec.h (original)
+++ eac3/ac3dec.h Tue Aug 21 22:50:09 2007
@@ -85,7 +85,13 @@ void ff_ac3_do_rematrixing(float (*trans
void ff_ac3_do_imdct_256(float *tmp_output, float *transform_coeffs,
MDCTContext *imdct_256, float *tmp_imdct);
+void ff_ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
+ int output_mode, float coef[AC3_MAX_CHANNELS][2]);
+
/** Adjustments in dB gain */
+#define LEVEL_PLUS_3DB 1.4142135623730950
+#define LEVEL_PLUS_1POINT5DB 1.1892071150027209
+#define LEVEL_MINUS_1POINT5DB 0.8408964152537145
#define LEVEL_MINUS_3DB 0.7071067811865476
#define LEVEL_MINUS_4POINT5DB 0.5946035575013605
#define LEVEL_MINUS_6DB 0.5000000000000000
Modified: eac3/checkout.sh
==============================================================================
--- eac3/checkout.sh (original)
+++ eac3/checkout.sh Tue Aug 21 22:50:09 2007
@@ -1,7 +1,7 @@
FILES="ac3.c ac3.h ac3tab.c ac3tab.h eac3dec.c eac3.h ac3dec.c ac3dec.h"
echo "checking out ffmpeg svn"
-for i in $FILES ac3_parser.c Makefile aac_ac3_parser.c aac_ac3_parser.h aac_parser.c allcodecs.c avcodec.h ../libavformat/allformats.h ../libavformat/raw.c allcodecs.h ac3enc.c; do
+for i in $FILES ac3_parser.c Makefile aac_ac3_parser.c aac_ac3_parser.h aac_parser.c allcodecs.c avcodec.h ../libavformat/allformats.h ../libavformat/raw.c allcodecs.h ac3enc.c ../ffmpeg.c; do
rm -f ffmpeg/libavcodec/$i
done
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk/ ffmpeg -r 10118
Modified: eac3/eac3.h
==============================================================================
--- eac3/eac3.h (original)
+++ eac3/eac3.h Tue Aug 21 22:50:09 2007
@@ -37,14 +37,6 @@
#define MAX_BLOCKS 6
#define MAX_SPX_CODES 18
-// TODO use new downmixing
-/** output configurations. */
-#define AC3_OUTPUT_UNMODIFIED 0x01
-#define AC3_OUTPUT_MONO 0x02
-#define AC3_OUTPUT_STEREO 0x04
-#define AC3_OUTPUT_DOLBY 0x08
-#define AC3_OUTPUT_LFEON 0x10
-
typedef struct EAC3Context{
AVCodecContext *avctx; ///< Parent context
int syncword;
@@ -63,10 +55,6 @@ typedef struct EAC3Context{
int chanmap; ///< Custom channel map
int mixmdate; ///< Mixing meta-data exists
int dmixmod; ///< Preferred stereo downmix mode
- int ltrtcmixlev; ///< Lt/Rt center mix level
- int lorocmixlev; ///< Lo/Ro center mix level
- int ltrtsurmixlev; ///< Lt/Rt surround mix level
- int lorosurmixlev; ///< Lo/Ro surround mix level
int lfemixlevcode; ///< lfe mix level code exists
int lfemixlevcod; ///< lfe mix level code
int pgmscl[2]; ///< Program scale factor
@@ -110,6 +98,7 @@ typedef struct EAC3Context{
int blksw[AC3_MAX_CHANNELS]; ///< Block switch flag
int dithflag[AC3_MAX_CHANNELS]; ///< Dither flag
float dynrng[2]; ///< Dynamic range gain word
+ float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients
int spxinu; ///< spectral extension in use
int chinspx[AC3_MAX_CHANNELS]; ///< Channel in spectral extension
int spxstrtf; ///< Spectral extension start copy frequency code
@@ -214,8 +203,6 @@ typedef struct EAC3Context{
float add_bias; ///< offset for float_to_int16 conversion
float mul_bias; ///< scaling for float_to_int16 conversion
-
- AC3ChannelMode blkoutput;
}EAC3Context;
/** Channel gain adaptive quantization mode */
Modified: eac3/eac3dec.c
==============================================================================
--- eac3/eac3dec.c (original)
+++ eac3/eac3dec.c Tue Aug 21 22:50:09 2007
@@ -40,6 +40,33 @@ static void get_eac3_transform_coeffs_ch
static void uncouple_channels(EAC3Context *s);
static void log_missing_feature(AVCodecContext *avctx, const char *log);
+/**
+ * Table for default stereo downmixing coefficients
+ * reference: Section 7.8.2 Downmixing Into Two Channels
+ */
+static const uint8_t eac3_default_coeffs[8][5][2] = {
+ { { 2, 7 }, { 7, 2 }, },
+ { { 4, 4 }, },
+ { { 2, 7 }, { 7, 2 }, },
+ { { 2, 7 }, { 5, 5 }, { 7, 2 }, },
+ { { 2, 7 }, { 7, 2 }, { 6, 6 }, },
+ { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 8, 8 }, },
+ { { 2, 7 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, },
+ { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, },
+};
+
+static const float mixlevels[9] = {
+ LEVEL_PLUS_3DB,
+ LEVEL_PLUS_1POINT5DB,
+ LEVEL_ONE,
+ LEVEL_MINUS_1POINT5DB,
+ LEVEL_MINUS_3DB,
+ LEVEL_MINUS_4POINT5DB,
+ LEVEL_MINUS_6DB,
+ LEVEL_ZERO,
+ LEVEL_MINUS_9DB
+};
+
static int parse_bsi(GetBitContext *gbc, EAC3Context *s){
int i, blk;
@@ -96,6 +123,14 @@ static int parse_bsi(GetBitContext *gbc,
//TODO default channel map based on acmod and lfeon
}
}
+
+ /* set stereo downmixing coefficients
+ reference: Section 7.8.2 Downmixing Into Two Channels */
+ for(i=0; i<s->nfchans; i++) {
+ s->downmix_coeffs[i][0] = mixlevels[eac3_default_coeffs[s->acmod][i][0]];
+ s->downmix_coeffs[i][1] = mixlevels[eac3_default_coeffs[s->acmod][i][1]];
+ }
+
GET_BITS(s->mixmdate, gbc, 1);
if(s->mixmdate){
/* Mixing metadata */
@@ -105,14 +140,22 @@ static int parse_bsi(GetBitContext *gbc,
}
if((s->acmod & 0x1) && (s->acmod > 0x2)){
/* if three front channels exist */
- GET_BITS(s->ltrtcmixlev, gbc, 3);
- GET_BITS(s->lorocmixlev, gbc, 3);
+ skip_bits(gbc, 3); //skip Lt/Rt center mix level
+ s->downmix_coeffs[1][0] = s->downmix_coeffs[1][1] = mixlevels[get_bits(gbc, 3)];
}
if(s->acmod & 0x4){
/* if a surround channel exists */
-
- GET_BITS(s->ltrtsurmixlev, gbc, 3);
- GET_BITS(s->lorosurmixlev, gbc, 3);
+ float surmixlev;
+ skip_bits(gbc, 3); //skip Lt/Rt surround mix level
+ surmixlev = mixlevels[get_bits(gbc, 3)];
+ if(s->acmod & 0x2){
+ //two surround channels
+ s->downmix_coeffs[s->acmod-4][0] = s->downmix_coeffs[s->acmod-3][1] =
+ surmixlev;
+ }else{
+ s->downmix_coeffs[s->acmod-2][0] = s->downmix_coeffs[s->acmod-2][1] =
+ surmixlev * LEVEL_MINUS_3DB;
+ }
}
if(s->lfeon){
/* if the LFE channel exists */
@@ -1235,10 +1278,10 @@ static void do_imdct(EAC3Context *ctx)
ctx->tmp_imdct);
}
/* apply window function, overlap/add output, save delay */
- ctx->dsp.vector_fmul_add_add(ctx->output[ch], ctx->tmp_output,
- ctx->window, ctx->delay[ch], 0,
+ ctx->dsp.vector_fmul_add_add(ctx->output[ch-1], ctx->tmp_output,
+ ctx->window, ctx->delay[ch-1], 0,
AC3_BLOCK_SIZE, 1);
- ctx->dsp.vector_fmul_reverse(ctx->delay[ch], ctx->tmp_output+256,
+ ctx->dsp.vector_fmul_reverse(ctx->delay[ch-1], ctx->tmp_output+256,
ctx->window, AC3_BLOCK_SIZE);
}
}
@@ -1272,7 +1315,20 @@ static int eac3_decode_frame(AVCodecCont
#ifdef DEBUG
av_log(NULL, AV_LOG_INFO, "bitrate = %i\n", avctx->bit_rate);
#endif
- avctx->channels = c->nfchans + c->lfeon; // TODO lfe
+
+ /* channel config */
+ if (avctx->channels == 0) {
+ avctx->channels = c->ntchans;
+ } else if(c->ntchans < avctx->channels) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot upmix EAC3 from %d to %d channels.\n",
+ c->ntchans, avctx->channels);
+ return -1;
+ }
+ if(avctx->channels > 2 && avctx->channels != c->ntchans) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot downmix EAC3 from %d to %d channels.\n",
+ c->ntchans, avctx->channels);
+ return -1;
+ }
for(blk = 0; blk < ff_eac3_blocks[c->numblkscod]; blk++){
for(i=0; i<AC3_MAX_CHANNELS+1; i++){
@@ -1295,7 +1351,6 @@ static int eac3_decode_frame(AVCodecCont
ff_ac3_do_rematrixing(c->transform_coeffs,
FFMIN(c->endmant[1], c->endmant[2]),
c->nrematbnds, c->rematflg);
- //TODO downmix_scaling...
/* apply scaling to coefficients (dialnorm, dynrng) */
for(ch=1; ch<=c->nfchans + c->lfeon; ch++) {
@@ -1311,29 +1366,13 @@ static int eac3_decode_frame(AVCodecCont
}
do_imdct(c);
- //TODO downmix
-
-#ifdef DEBUG
- av_log(avctx, AV_LOG_INFO, "channels = %i\n", avctx->channels);
-#endif
- // set output mode
- c->blkoutput = 0;
- if (avctx->channels == 1) {
- c->blkoutput |= AC3_OUTPUT_MONO;
- } else if (avctx->channels == 2) {
- c->blkoutput |= AC3_OUTPUT_STEREO;
- } else {
- if (avctx->channels && avctx->channels < c->nfchans + c->lfeon )
- av_log(avctx, AV_LOG_INFO, "ac3_decoder: E-AC3 Source Channels Are Less Then Specified %d: Output to %d Channels\n",avctx->channels, c->nfchans + c->lfeon);
- c->blkoutput |= AC3_OUTPUT_UNMODIFIED;
- if (c->lfeon)
- c->blkoutput |= AC3_OUTPUT_LFEON;
- avctx->channels = c->nfchans + c->lfeon;
+ if(avctx->channels != c->ntchans){
+ ff_ac3_downmix(c->output, c->nfchans, avctx->channels, c->downmix_coeffs);
}
// convert float to 16-bit integer
- for(ch = 1; ch<=c->nfchans + c->lfeon; ch++) { // <- out_channels TODO
+ for(ch = 0; ch<avctx->channels; ch++) {
for(i=0; i<AC3_BLOCK_SIZE; i++) {
c->output[ch][i] = c->output[ch][i] * c->mul_bias +
c->add_bias;
@@ -1342,7 +1381,7 @@ static int eac3_decode_frame(AVCodecCont
AC3_BLOCK_SIZE);
}
for (k = 0; k < AC3_BLOCK_SIZE; k++) {
- for (i = 1; i <= avctx->channels; i++) {
+ for (i = 0; i < avctx->channels; i++) {
*(out_samples++) = c->int_output[i][k];
}
}
Modified: eac3/ffmpeg.patch
==============================================================================
--- eac3/ffmpeg.patch (original)
+++ eac3/ffmpeg.patch Tue Aug 21 22:50:09 2007
@@ -67,6 +67,15 @@ Index: libavcodec/aac_ac3_parser.c
&samples);
if (len == 0) {
/* no sync found : move by one byte (inefficient, but simple!) */
+@@ -59,7 +59,7 @@
+ /* update codec info */
+ avctx->sample_rate = sample_rate;
+ /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */
+- if(avctx->codec_id == CODEC_ID_AC3){
++ if(avctx->codec_id == CODEC_ID_AC3 || avctx->codec_id == CODEC_ID_EAC3){
+ if(avctx->channels!=1 && avctx->channels!=2){
+ avctx->channels = channels;
+ }
Index: libavcodec/aac_ac3_parser.h
===================================================================
--- libavcodec/aac_ac3_parser.h (wersja 10118)
@@ -183,3 +192,15 @@ Index: libavcodec/ac3enc.c
frame_bits += compute_mantissa_size(s, bap[i][ch],
s->nb_coefs[ch]);
}
+Index: ffmpeg.c
+===================================================================
+--- ffmpeg.c (wersja 10118)
++++ ffmpeg.c (kopia robocza)
+@@ -1569,6 +1569,7 @@
+ } else {
+ if (codec->channels != icodec->channels &&
+ (icodec->codec_id == CODEC_ID_AC3 ||
++ icodec->codec_id == CODEC_ID_EAC3 ||
+ icodec->codec_id == CODEC_ID_DTS)) {
+ /* Special case for 5:1 AC3 and DTS input */
+ /* and mono or stereo output */
More information about the FFmpeg-soc
mailing list