Browse Source

stereo decorrelation support by (Justin Ruggles jruggle earthlink net>)

Originally committed as revision 5528 to svn://svn.ffmpeg.org/ffmpeg/trunk
tags/v0.5
Michael Niedermayer 19 years ago
parent
commit
f33aa12011
3 changed files with 112 additions and 28 deletions
  1. +108
    -24
      libavcodec/flacenc.c
  2. +2
    -2
      tests/ffmpeg.regression.ref
  3. +2
    -2
      tests/rotozoom.regression.ref

+ 108
- 24
libavcodec/flacenc.c View File

@@ -177,7 +177,12 @@ static int flac_encode_init(AVCodecContext *avctx)
s->blocksize = select_blocksize(s->samplerate);
avctx->frame_size = s->blocksize;

s->max_framesize = 14 + (s->blocksize * s->channels * 2);
/* set maximum encoded frame size in verbatim mode */
if(s->channels == 2) {
s->max_framesize = 14 + ((s->blocksize * 33 + 7) >> 3);
} else {
s->max_framesize = 14 + (s->blocksize * s->channels * 2);
}

streaminfo = av_malloc(FLAC_STREAMINFO_SIZE);
write_streaminfo(s, streaminfo);
@@ -192,7 +197,7 @@ static int flac_encode_init(AVCodecContext *avctx)
return 0;
}

static int init_frame(FlacEncodeContext *s)
static void init_frame(FlacEncodeContext *s)
{
int i, ch;
FlacFrame *frame;
@@ -221,13 +226,6 @@ static int init_frame(FlacEncodeContext *s)
for(ch=0; ch<s->channels; ch++) {
frame->subframes[ch].obits = 16;
}
if(s->channels == 2) {
frame->ch_mode = FLAC_CHMODE_LEFT_RIGHT;
} else {
frame->ch_mode = FLAC_CHMODE_NOT_STEREO;
}

return 0;
}

/**
@@ -246,6 +244,94 @@ static void copy_samples(FlacEncodeContext *s, int16_t *samples)
}
}

static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n)
{
int i, best;
int32_t lt, rt;
uint64_t left, right, mid, side;
uint64_t score[4];

/* calculate sum of squares for each channel */
left = right = mid = side = 0;
for(i=2; i<n; i++) {
lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2];
rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2];
mid += ABS((lt + rt) >> 1);
side += ABS(lt - rt);
left += ABS(lt);
right += ABS(rt);
}

/* calculate score for each mode */
score[0] = left + right;
score[1] = left + side;
score[2] = right + side;
score[3] = mid + side;

/* return mode with lowest score */
best = 0;
for(i=1; i<4; i++) {
if(score[i] < score[best]) {
best = i;
}
}
if(best == 0) {
return FLAC_CHMODE_LEFT_RIGHT;
} else if(best == 1) {
return FLAC_CHMODE_LEFT_SIDE;
} else if(best == 2) {
return FLAC_CHMODE_RIGHT_SIDE;
} else {
return FLAC_CHMODE_MID_SIDE;
}
}

/**
* Perform stereo channel decorrelation
*/
static void channel_decorrelation(FlacEncodeContext *ctx)
{
FlacFrame *frame;
int32_t *left, *right;
int i, n;

frame = &ctx->frame;
n = frame->blocksize;
left = frame->subframes[0].samples;
right = frame->subframes[1].samples;

if(ctx->channels != 2) {
frame->ch_mode = FLAC_CHMODE_NOT_STEREO;
return;
}

frame->ch_mode = estimate_stereo_mode(left, right, n);

/* perform decorrelation and adjust bits-per-sample */
if(frame->ch_mode == FLAC_CHMODE_LEFT_RIGHT) {
return;
}
if(frame->ch_mode == FLAC_CHMODE_MID_SIDE) {
int32_t tmp;
for(i=0; i<n; i++) {
tmp = left[i];
left[i] = (tmp + right[i]) >> 1;
right[i] = tmp - right[i];
}
frame->subframes[1].obits++;
} else if(frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) {
for(i=0; i<n; i++) {
right[i] = left[i] - right[i];
}
frame->subframes[1].obits++;
} else {
for(i=0; i<n; i++) {
left[i] -= right[i];
}
frame->subframes[0].obits++;
}
}

static void encode_residual_verbatim(FlacEncodeContext *s, int ch)
{
FlacFrame *frame;
@@ -359,19 +445,15 @@ output_frame_header(FlacEncodeContext *s)
put_bits(&s->pb, 3, 4); /* bits-per-sample code */
put_bits(&s->pb, 1, 0);
write_utf8(&s->pb, s->frame_count);
if(frame->bs_code[1] > 0) {
if(frame->bs_code[1] < 256) {
put_bits(&s->pb, 8, frame->bs_code[1]);
} else {
put_bits(&s->pb, 16, frame->bs_code[1]);
}
if(frame->bs_code[0] == 6) {
put_bits(&s->pb, 8, frame->bs_code[1]);
} else if(frame->bs_code[0] == 7) {
put_bits(&s->pb, 16, frame->bs_code[1]);
}
if(s->sr_code[1] > 0) {
if(s->sr_code[1] < 256) {
put_bits(&s->pb, 8, s->sr_code[1]);
} else {
put_bits(&s->pb, 16, s->sr_code[1]);
}
if(s->sr_code[0] == 12) {
put_bits(&s->pb, 8, s->sr_code[1]);
} else if(s->sr_code[0] > 12) {
put_bits(&s->pb, 16, s->sr_code[1]);
}
flush_put_bits(&s->pb);
crc = av_crc(av_crc07, 0, s->pb.buf, put_bits_count(&s->pb)>>3);
@@ -493,12 +575,12 @@ static int flac_encode_frame(AVCodecContext *avctx, uint8_t *frame,
s = avctx->priv_data;

s->blocksize = avctx->frame_size;
if(init_frame(s)) {
return 0;
}
init_frame(s);

copy_samples(s, samples);

channel_decorrelation(s);

for(ch=0; ch<s->channels; ch++) {
encode_residual(s, ch);
}
@@ -532,6 +614,8 @@ static int flac_encode_frame(AVCodecContext *avctx, uint8_t *frame,

static int flac_encode_close(AVCodecContext *avctx)
{
av_freep(&avctx->extradata);
avctx->extradata_size = 0;
av_freep(&avctx->coded_frame);
return 0;
}


+ 2
- 2
tests/ffmpeg.regression.ref View File

@@ -176,7 +176,7 @@ stddev:1050.18 PSNR:35.89 bytes:1054720
264236 ./data/a-adpcm_yam.wav
e92cec8c07913ffb91ad2b11f79cdc00 *./data/out.wav
stddev:18312.68 PSNR:11.06 bytes:1056768
7bcc7daf968fc489c9b4b7aca5ae380d *./data/a-flac.flac
799336 ./data/a-flac.flac
9ed4957501a56ce9d4e6a6611553a45f *./data/a-flac.flac
801577 ./data/a-flac.flac
0116cdcefd0aeae3ab8e5140c19c725d *./data/out.wav
stddev: 51.59 PSNR:62.07 bytes:1032192

+ 2
- 2
tests/rotozoom.regression.ref View File

@@ -176,7 +176,7 @@ stddev:1050.18 PSNR:35.89 bytes:1054720
264236 ./data/a-adpcm_yam.wav
e92cec8c07913ffb91ad2b11f79cdc00 *./data/out.wav
stddev:18312.68 PSNR:11.06 bytes:1056768
7bcc7daf968fc489c9b4b7aca5ae380d *./data/a-flac.flac
799336 ./data/a-flac.flac
9ed4957501a56ce9d4e6a6611553a45f *./data/a-flac.flac
801577 ./data/a-flac.flac
0116cdcefd0aeae3ab8e5140c19c725d *./data/out.wav
stddev: 51.59 PSNR:62.07 bytes:1032192

Loading…
Cancel
Save