Originally committed as revision 1514 to svn://svn.ffmpeg.org/ffmpeg/trunk
Fabrice Bellard authored on 2003/01/27 18:21:30... | ... |
@@ -72,7 +72,7 @@ void avcodec_register_all(void) |
72 | 72 |
register_avcodec(&rv10_decoder); |
73 | 73 |
register_avcodec(&svq1_decoder); |
74 | 74 |
register_avcodec(&dvvideo_decoder); |
75 |
- // register_avcodec(&dvaudio_decoder); |
|
75 |
+ register_avcodec(&dvaudio_decoder); |
|
76 | 76 |
register_avcodec(&mjpeg_decoder); |
77 | 77 |
register_avcodec(&mjpegb_decoder); |
78 | 78 |
register_avcodec(&mp2_decoder); |
... | ... |
@@ -634,7 +634,6 @@ AVCodec dvvideo_decoder = { |
634 | 634 |
typedef struct DVAudioDecodeContext { |
635 | 635 |
AVCodecContext *avctx; |
636 | 636 |
GetBitContext gb; |
637 |
- |
|
638 | 637 |
} DVAudioDecodeContext; |
639 | 638 |
|
640 | 639 |
static int dvaudio_decode_init(AVCodecContext *avctx) |
... | ... |
@@ -643,13 +642,126 @@ static int dvaudio_decode_init(AVCodecContext *avctx) |
643 | 643 |
return 0; |
644 | 644 |
} |
645 | 645 |
|
646 |
+static UINT16 dv_audio_12to16(UINT16 sample) |
|
647 |
+{ |
|
648 |
+ UINT16 shift, result; |
|
649 |
+ |
|
650 |
+ sample = (sample < 0x800) ? sample : sample | 0xf000; |
|
651 |
+ shift = (sample & 0xf00) >> 8; |
|
652 |
+ |
|
653 |
+ if (shift < 0x2 || shift > 0xd) { |
|
654 |
+ result = sample; |
|
655 |
+ } else if (shift < 0x8) { |
|
656 |
+ shift--; |
|
657 |
+ result = (sample - (256 * shift)) << shift; |
|
658 |
+ } else { |
|
659 |
+ shift = 0xe - shift; |
|
660 |
+ result = ((sample + ((256 * shift) + 1)) << shift) - 1; |
|
661 |
+ } |
|
662 |
+ |
|
663 |
+ return result; |
|
664 |
+} |
|
665 |
+ |
|
646 | 666 |
/* NOTE: exactly one frame must be given (120000 bytes for NTSC, |
647 |
- 144000 bytes for PAL) */ |
|
667 |
+ 144000 bytes for PAL) |
|
668 |
+ |
|
669 |
+ There's a couple of assumptions being made here: |
|
670 |
+ 1. We don't do any kind of audio error correction. It means, |
|
671 |
+ that erroneous samples 0x8000 are being passed upwards. |
|
672 |
+ Do we need to silence erroneous samples ? Average them ? |
|
673 |
+ 2. We don't do software emphasis. |
|
674 |
+ 3. We are not checking for 'speed' argument being valid. |
|
675 |
+ 4. Audio is always returned as 16bit linear samples: 12bit |
|
676 |
+ nonlinear samples are converted into 16bit linear ones. |
|
677 |
+*/ |
|
648 | 678 |
static int dvaudio_decode_frame(AVCodecContext *avctx, |
649 | 679 |
void *data, int *data_size, |
650 | 680 |
UINT8 *buf, int buf_size) |
651 | 681 |
{ |
652 |
- // DVAudioDecodeContext *s = avctx->priv_data; |
|
682 |
+ DVVideoDecodeContext *s = avctx->priv_data; |
|
683 |
+ const UINT16 (*unshuffle)[9]; |
|
684 |
+ int smpls, freq, quant, sys, stride, difseg, ad, dp, nb_dif_segs, i; |
|
685 |
+ UINT16 lc, rc; |
|
686 |
+ UINT8 *buf_ptr; |
|
687 |
+ |
|
688 |
+ /* parse id */ |
|
689 |
+ init_get_bits(&s->gb, &buf[AAUX_OFFSET], 5*8); |
|
690 |
+ i = get_bits(&s->gb, 8); |
|
691 |
+ if (i != 0x50) { /* No audio ? */ |
|
692 |
+ *data_size = 0; |
|
693 |
+ return buf_size; |
|
694 |
+ } |
|
695 |
+ |
|
696 |
+ get_bits(&s->gb, 1); /* 0 - locked audio, 1 - unlocked audio */ |
|
697 |
+ skip_bits(&s->gb, 1); |
|
698 |
+ smpls = get_bits(&s->gb, 6); /* samples in this frame - min. samples */ |
|
699 |
+ |
|
700 |
+ skip_bits(&s->gb, 8); |
|
701 |
+ |
|
702 |
+ skip_bits(&s->gb, 2); |
|
703 |
+ sys = get_bits(&s->gb, 1); /* 0 - 60 fields, 1 = 50 fields */ |
|
704 |
+ skip_bits(&s->gb, 5); |
|
705 |
+ |
|
706 |
+ get_bits(&s->gb, 1); /* 0 - emphasis on, 1 - emphasis off */ |
|
707 |
+ get_bits(&s->gb, 1); /* 0 - reserved, 1 - emphasis time constant 50/15us */ |
|
708 |
+ freq = get_bits(&s->gb, 3); /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */ |
|
709 |
+ quant = get_bits(&s->gb, 3); /* 0 - 16bit linear, 1 - 12bit nonlinear */ |
|
710 |
+ |
|
711 |
+ if (quant > 1) |
|
712 |
+ return -1; /* Unsupported quantization */ |
|
713 |
+ |
|
714 |
+ avctx->sample_rate = dv_audio_frequency[freq]; |
|
715 |
+ // What about: |
|
716 |
+ // avctx->bit_rate = |
|
717 |
+ // avctx->frame_size = |
|
718 |
+ |
|
719 |
+ *data_size = (dv_audio_min_samples[sys][freq] + smpls) * |
|
720 |
+ avctx->channels * 2; |
|
721 |
+ |
|
722 |
+ if (sys) { |
|
723 |
+ nb_dif_segs = 12; |
|
724 |
+ stride = 108; |
|
725 |
+ unshuffle = dv_place_audio50; |
|
726 |
+ } else { |
|
727 |
+ nb_dif_segs = 10; |
|
728 |
+ stride = 90; |
|
729 |
+ unshuffle = dv_place_audio60; |
|
730 |
+ } |
|
731 |
+ |
|
732 |
+ /* for each DIF segment */ |
|
733 |
+ buf_ptr = buf; |
|
734 |
+ for (difseg = 0; difseg < nb_dif_segs; difseg++) { |
|
735 |
+ buf_ptr += 6 * 80; /* skip DIF segment header */ |
|
736 |
+ for (ad = 0; ad < 9; ad++) { |
|
737 |
+ |
|
738 |
+ for (dp = 8; dp < 80; dp+=2) { |
|
739 |
+ if (quant == 0) { /* 16bit quantization */ |
|
740 |
+ i = unshuffle[difseg][ad] + (dp - 8)/2 * stride; |
|
741 |
+ ((short *)data)[i] = (buf_ptr[dp] << 8) | buf_ptr[dp+1]; |
|
742 |
+ } else { /* 12bit quantization */ |
|
743 |
+ if (difseg >= nb_dif_segs/2) |
|
744 |
+ goto out; /* We're not doing 4ch at this time */ |
|
745 |
+ |
|
746 |
+ lc = ((UINT16)buf_ptr[dp] << 4) | |
|
747 |
+ ((UINT16)buf_ptr[dp+2] >> 4); |
|
748 |
+ rc = ((UINT16)buf_ptr[dp+1] << 4) | |
|
749 |
+ ((UINT16)buf_ptr[dp+2] & 0x0f); |
|
750 |
+ lc = dv_audio_12to16(lc); |
|
751 |
+ rc = dv_audio_12to16(rc); |
|
752 |
+ |
|
753 |
+ i = unshuffle[difseg][ad] + (dp - 8)/3 * stride; |
|
754 |
+ ((short *)data)[i] = lc; |
|
755 |
+ i = unshuffle[difseg+nb_dif_segs/2][ad] + (dp - 8)/3 * stride; |
|
756 |
+ ((short *)data)[i] = rc; |
|
757 |
+ ++dp; |
|
758 |
+ } |
|
759 |
+ } |
|
760 |
+ |
|
761 |
+ buf_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ |
|
762 |
+ } |
|
763 |
+ } |
|
764 |
+ |
|
765 |
+out: |
|
653 | 766 |
return buf_size; |
654 | 767 |
} |
655 | 768 |
|
... | ... |
@@ -18,6 +18,7 @@ |
18 | 18 |
*/ |
19 | 19 |
|
20 | 20 |
#define NB_DV_VLC 409 |
21 |
+#define AAUX_OFFSET (80*6 + 80*16*3 + 3) |
|
21 | 22 |
|
22 | 23 |
static const UINT16 dv_vlc_bits[409] = { |
23 | 24 |
0x0000, 0x0002, 0x0007, 0x0008, 0x0009, 0x0014, 0x0015, 0x0016, |
... | ... |
@@ -905,3 +906,41 @@ static const UINT16 dv_place_411[1350] = { |
905 | 905 |
0x0834, 0x2320, 0x2f44, 0x3810, 0x1658, |
906 | 906 |
}; |
907 | 907 |
|
908 |
+static const UINT16 dv_place_audio60[10][9] = { |
|
909 |
+ { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */ |
|
910 |
+ { 6, 36, 66, 26, 56, 86, 16, 46, 76 }, |
|
911 |
+ { 12, 42, 72, 2, 32, 62, 22, 52, 82 }, |
|
912 |
+ { 18, 48, 78, 8, 38, 68, 28, 58, 88 }, |
|
913 |
+ { 24, 54, 84, 14, 44, 74, 4, 34, 64 }, |
|
914 |
+ |
|
915 |
+ { 1, 31, 61, 21, 51, 81, 11, 41, 71 }, /* 2nd channel */ |
|
916 |
+ { 7, 37, 67, 27, 57, 87, 17, 47, 77 }, |
|
917 |
+ { 13, 43, 73, 3, 33, 63, 23, 53, 83 }, |
|
918 |
+ { 19, 49, 79, 9, 39, 69, 29, 59, 89 }, |
|
919 |
+ { 25, 55, 85, 15, 45, 75, 5, 35, 65 }, |
|
920 |
+}; |
|
921 |
+ |
|
922 |
+static const UINT16 dv_place_audio50[12][9] = { |
|
923 |
+ { 0, 36, 72, 26, 62, 98, 16, 52, 88}, /* 1st channel */ |
|
924 |
+ { 6, 42, 78, 32, 68, 104, 22, 58, 94}, |
|
925 |
+ { 12, 48, 84, 2, 38, 74, 28, 64, 100}, |
|
926 |
+ { 18, 54, 90, 8, 44, 80, 34, 70, 106}, |
|
927 |
+ { 24, 60, 96, 14, 50, 86, 4, 40, 76}, |
|
928 |
+ { 30, 66, 102, 20, 56, 92, 10, 46, 82}, |
|
929 |
+ |
|
930 |
+ { 1, 37, 73, 27, 63, 99, 17, 53, 89}, /* 2nd channel */ |
|
931 |
+ { 7, 43, 79, 33, 69, 105, 23, 59, 95}, |
|
932 |
+ { 13, 49, 85, 3, 39, 75, 29, 65, 101}, |
|
933 |
+ { 19, 55, 91, 9, 45, 81, 35, 71, 107}, |
|
934 |
+ { 25, 61, 97, 15, 51, 87, 5, 41, 77}, |
|
935 |
+ { 31, 67, 103, 21, 57, 93, 11, 47, 83}, |
|
936 |
+}; |
|
937 |
+ |
|
938 |
+static const int dv_audio_frequency[3] = { |
|
939 |
+ 48000, 44100, 32000, |
|
940 |
+}; |
|
941 |
+ |
|
942 |
+static const int dv_audio_min_samples[2][3] = { |
|
943 |
+ { 1580, 1452, 1053 }, /* 60 fields */ |
|
944 |
+ { 1896, 1742, 1264 }, /* 50 fileds */ |
|
945 |
+}; |
... | ... |
@@ -22,15 +22,17 @@ |
22 | 22 |
#define PAL_FRAME_SIZE 144000 |
23 | 23 |
|
24 | 24 |
typedef struct DVDemuxContext { |
25 |
- int is_audio; |
|
25 |
+ int is_audio; |
|
26 |
+ uint8_t buf[PAL_FRAME_SIZE]; |
|
27 |
+ int size; |
|
26 | 28 |
} DVDemuxContext; |
27 | 29 |
|
28 | 30 |
/* raw input */ |
29 | 31 |
static int dv_read_header(AVFormatContext *s, |
30 | 32 |
AVFormatParameters *ap) |
31 | 33 |
{ |
32 |
- AVStream *vst; |
|
33 |
- // AVStream *ast; |
|
34 |
+ AVStream *vst, *ast; |
|
35 |
+ DVDemuxContext *c = s->priv_data; |
|
34 | 36 |
|
35 | 37 |
vst = av_new_stream(s, 0); |
36 | 38 |
if (!vst) |
... | ... |
@@ -38,42 +40,46 @@ static int dv_read_header(AVFormatContext *s, |
38 | 38 |
vst->codec.codec_type = CODEC_TYPE_VIDEO; |
39 | 39 |
vst->codec.codec_id = CODEC_ID_DVVIDEO; |
40 | 40 |
|
41 |
-#if 0 |
|
41 |
+ |
|
42 | 42 |
ast = av_new_stream(s, 1); |
43 | 43 |
if (!ast) |
44 | 44 |
return AVERROR_NOMEM; |
45 | 45 |
|
46 | 46 |
ast->codec.codec_type = CODEC_TYPE_AUDIO; |
47 | 47 |
ast->codec.codec_id = CODEC_ID_DVAUDIO; |
48 |
-#endif |
|
48 |
+ ast->codec.channels = 2; |
|
49 |
+ c->is_audio = 0; |
|
50 |
+ |
|
49 | 51 |
return 0; |
50 | 52 |
} |
51 | 53 |
|
52 | 54 |
/* XXX: build fake audio stream when DV audio decoder will be finished */ |
53 | 55 |
static int dv_read_packet(AVFormatContext *s, AVPacket *pkt) |
54 | 56 |
{ |
55 |
- int ret, size, dsf; |
|
56 |
- uint8_t buf[4]; |
|
57 |
+ int ret, dsf; |
|
58 |
+ DVDemuxContext *c = s->priv_data; |
|
57 | 59 |
|
58 |
- ret = get_buffer(&s->pb, buf, 4); |
|
59 |
- if (ret <= 0) |
|
60 |
- return -EIO; |
|
61 |
- dsf = buf[3] & 0x80; |
|
62 |
- if (!dsf) |
|
63 |
- size = NTSC_FRAME_SIZE; |
|
64 |
- else |
|
65 |
- size = PAL_FRAME_SIZE; |
|
60 |
+ if (!c->is_audio) { |
|
61 |
+ ret = get_buffer(&s->pb, c->buf, 4); |
|
62 |
+ if (ret <= 0) |
|
63 |
+ return -EIO; |
|
64 |
+ dsf = c->buf[3] & 0x80; |
|
65 |
+ if (!dsf) |
|
66 |
+ c->size = NTSC_FRAME_SIZE; |
|
67 |
+ else |
|
68 |
+ c->size = PAL_FRAME_SIZE; |
|
69 |
+ |
|
70 |
+ ret = get_buffer(&s->pb, c->buf + 4, c->size - 4); |
|
71 |
+ if (ret <= 0) |
|
72 |
+ return -EIO; |
|
73 |
+ } |
|
66 | 74 |
|
67 |
- if (av_new_packet(pkt, size) < 0) |
|
75 |
+ if (av_new_packet(pkt, c->size) < 0) |
|
68 | 76 |
return -EIO; |
69 | 77 |
|
70 |
- pkt->stream_index = 0; |
|
71 |
- memcpy(pkt->data, buf, 4); |
|
72 |
- ret = get_buffer(&s->pb, pkt->data + 4, size - 4); |
|
73 |
- if (ret <= 0) { |
|
74 |
- av_free_packet(pkt); |
|
75 |
- return -EIO; |
|
76 |
- } |
|
78 |
+ pkt->stream_index = c->is_audio; |
|
79 |
+ c->is_audio = !c->is_audio; |
|
80 |
+ memcpy(pkt->data, c->buf, c->size); |
|
77 | 81 |
return ret; |
78 | 82 |
} |
79 | 83 |
|