summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-01-27 09:21:30 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-01-27 09:21:30 +0000
commit425ed6e223b8dd190e9fbeb4a41c6479f3fc8df0 (patch)
tree57fbdc23c600efc2cc0f99df119b9a2752b9ac5a /libavcodec
parent850742d785cd566204b112d77c018e9f2b701239 (diff)
DV audio decoder by Roman Shaposhnick
Originally committed as revision 1514 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/allcodecs.c2
-rw-r--r--libavcodec/dv.c118
-rw-r--r--libavcodec/dvdata.h39
3 files changed, 155 insertions, 4 deletions
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index a5d2e41cfb..cc06645395 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -72,7 +72,7 @@ void avcodec_register_all(void)
register_avcodec(&rv10_decoder);
register_avcodec(&svq1_decoder);
register_avcodec(&dvvideo_decoder);
- // register_avcodec(&dvaudio_decoder);
+ register_avcodec(&dvaudio_decoder);
register_avcodec(&mjpeg_decoder);
register_avcodec(&mjpegb_decoder);
register_avcodec(&mp2_decoder);
diff --git a/libavcodec/dv.c b/libavcodec/dv.c
index f312c0264c..554b593e7a 100644
--- a/libavcodec/dv.c
+++ b/libavcodec/dv.c
@@ -634,7 +634,6 @@ AVCodec dvvideo_decoder = {
typedef struct DVAudioDecodeContext {
AVCodecContext *avctx;
GetBitContext gb;
-
} DVAudioDecodeContext;
static int dvaudio_decode_init(AVCodecContext *avctx)
@@ -643,13 +642,126 @@ static int dvaudio_decode_init(AVCodecContext *avctx)
return 0;
}
+static UINT16 dv_audio_12to16(UINT16 sample)
+{
+ UINT16 shift, result;
+
+ sample = (sample < 0x800) ? sample : sample | 0xf000;
+ shift = (sample & 0xf00) >> 8;
+
+ if (shift < 0x2 || shift > 0xd) {
+ result = sample;
+ } else if (shift < 0x8) {
+ shift--;
+ result = (sample - (256 * shift)) << shift;
+ } else {
+ shift = 0xe - shift;
+ result = ((sample + ((256 * shift) + 1)) << shift) - 1;
+ }
+
+ return result;
+}
+
/* NOTE: exactly one frame must be given (120000 bytes for NTSC,
- 144000 bytes for PAL) */
+ 144000 bytes for PAL)
+
+ There's a couple of assumptions being made here:
+ 1. We don't do any kind of audio error correction. It means,
+ that erroneous samples 0x8000 are being passed upwards.
+ Do we need to silence erroneous samples ? Average them ?
+ 2. We don't do software emphasis.
+ 3. We are not checking for 'speed' argument being valid.
+ 4. Audio is always returned as 16bit linear samples: 12bit
+ nonlinear samples are converted into 16bit linear ones.
+*/
static int dvaudio_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
UINT8 *buf, int buf_size)
{
- // DVAudioDecodeContext *s = avctx->priv_data;
+ DVVideoDecodeContext *s = avctx->priv_data;
+ const UINT16 (*unshuffle)[9];
+ int smpls, freq, quant, sys, stride, difseg, ad, dp, nb_dif_segs, i;
+ UINT16 lc, rc;
+ UINT8 *buf_ptr;
+
+ /* parse id */
+ init_get_bits(&s->gb, &buf[AAUX_OFFSET], 5*8);
+ i = get_bits(&s->gb, 8);
+ if (i != 0x50) { /* No audio ? */
+ *data_size = 0;
+ return buf_size;
+ }
+
+ get_bits(&s->gb, 1); /* 0 - locked audio, 1 - unlocked audio */
+ skip_bits(&s->gb, 1);
+ smpls = get_bits(&s->gb, 6); /* samples in this frame - min. samples */
+
+ skip_bits(&s->gb, 8);
+
+ skip_bits(&s->gb, 2);
+ sys = get_bits(&s->gb, 1); /* 0 - 60 fields, 1 = 50 fields */
+ skip_bits(&s->gb, 5);
+
+ get_bits(&s->gb, 1); /* 0 - emphasis on, 1 - emphasis off */
+ get_bits(&s->gb, 1); /* 0 - reserved, 1 - emphasis time constant 50/15us */
+ freq = get_bits(&s->gb, 3); /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
+ quant = get_bits(&s->gb, 3); /* 0 - 16bit linear, 1 - 12bit nonlinear */
+
+ if (quant > 1)
+ return -1; /* Unsupported quantization */
+
+ avctx->sample_rate = dv_audio_frequency[freq];
+ // What about:
+ // avctx->bit_rate =
+ // avctx->frame_size =
+
+ *data_size = (dv_audio_min_samples[sys][freq] + smpls) *
+ avctx->channels * 2;
+
+ if (sys) {
+ nb_dif_segs = 12;
+ stride = 108;
+ unshuffle = dv_place_audio50;
+ } else {
+ nb_dif_segs = 10;
+ stride = 90;
+ unshuffle = dv_place_audio60;
+ }
+
+ /* for each DIF segment */
+ buf_ptr = buf;
+ for (difseg = 0; difseg < nb_dif_segs; difseg++) {
+ buf_ptr += 6 * 80; /* skip DIF segment header */
+ for (ad = 0; ad < 9; ad++) {
+
+ for (dp = 8; dp < 80; dp+=2) {
+ if (quant == 0) { /* 16bit quantization */
+ i = unshuffle[difseg][ad] + (dp - 8)/2 * stride;
+ ((short *)data)[i] = (buf_ptr[dp] << 8) | buf_ptr[dp+1];
+ } else { /* 12bit quantization */
+ if (difseg >= nb_dif_segs/2)
+ goto out; /* We're not doing 4ch at this time */
+
+ lc = ((UINT16)buf_ptr[dp] << 4) |
+ ((UINT16)buf_ptr[dp+2] >> 4);
+ rc = ((UINT16)buf_ptr[dp+1] << 4) |
+ ((UINT16)buf_ptr[dp+2] & 0x0f);
+ lc = dv_audio_12to16(lc);
+ rc = dv_audio_12to16(rc);
+
+ i = unshuffle[difseg][ad] + (dp - 8)/3 * stride;
+ ((short *)data)[i] = lc;
+ i = unshuffle[difseg+nb_dif_segs/2][ad] + (dp - 8)/3 * stride;
+ ((short *)data)[i] = rc;
+ ++dp;
+ }
+ }
+
+ buf_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
+ }
+ }
+
+out:
return buf_size;
}
diff --git a/libavcodec/dvdata.h b/libavcodec/dvdata.h
index b5c1f56077..4e1fc39c7f 100644
--- a/libavcodec/dvdata.h
+++ b/libavcodec/dvdata.h
@@ -18,6 +18,7 @@
*/
#define NB_DV_VLC 409
+#define AAUX_OFFSET (80*6 + 80*16*3 + 3)
static const UINT16 dv_vlc_bits[409] = {
0x0000, 0x0002, 0x0007, 0x0008, 0x0009, 0x0014, 0x0015, 0x0016,
@@ -905,3 +906,41 @@ static const UINT16 dv_place_411[1350] = {
0x0834, 0x2320, 0x2f44, 0x3810, 0x1658,
};
+static const UINT16 dv_place_audio60[10][9] = {
+ { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */
+ { 6, 36, 66, 26, 56, 86, 16, 46, 76 },
+ { 12, 42, 72, 2, 32, 62, 22, 52, 82 },
+ { 18, 48, 78, 8, 38, 68, 28, 58, 88 },
+ { 24, 54, 84, 14, 44, 74, 4, 34, 64 },
+
+ { 1, 31, 61, 21, 51, 81, 11, 41, 71 }, /* 2nd channel */
+ { 7, 37, 67, 27, 57, 87, 17, 47, 77 },
+ { 13, 43, 73, 3, 33, 63, 23, 53, 83 },
+ { 19, 49, 79, 9, 39, 69, 29, 59, 89 },
+ { 25, 55, 85, 15, 45, 75, 5, 35, 65 },
+};
+
+static const UINT16 dv_place_audio50[12][9] = {
+ { 0, 36, 72, 26, 62, 98, 16, 52, 88}, /* 1st channel */
+ { 6, 42, 78, 32, 68, 104, 22, 58, 94},
+ { 12, 48, 84, 2, 38, 74, 28, 64, 100},
+ { 18, 54, 90, 8, 44, 80, 34, 70, 106},
+ { 24, 60, 96, 14, 50, 86, 4, 40, 76},
+ { 30, 66, 102, 20, 56, 92, 10, 46, 82},
+
+ { 1, 37, 73, 27, 63, 99, 17, 53, 89}, /* 2nd channel */
+ { 7, 43, 79, 33, 69, 105, 23, 59, 95},
+ { 13, 49, 85, 3, 39, 75, 29, 65, 101},
+ { 19, 55, 91, 9, 45, 81, 35, 71, 107},
+ { 25, 61, 97, 15, 51, 87, 5, 41, 77},
+ { 31, 67, 103, 21, 57, 93, 11, 47, 83},
+};
+
+static const int dv_audio_frequency[3] = {
+ 48000, 44100, 32000,
+};
+
+static const int dv_audio_min_samples[2][3] = {
+ { 1580, 1452, 1053 }, /* 60 fields */
+ { 1896, 1742, 1264 }, /* 50 fileds */
+};