Add support for VDPAU video out, including hardware decoding.
[mplayer/glamo.git] / libmpcodecs / ad_dvdpcm.c
blob19625949611c8f098b11b39dfef21708fc20c322
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
5 #include "config.h"
6 #include "mp_msg.h"
7 #include "help_mp.h"
8 #include "ad_internal.h"
10 static ad_info_t info =
12 "Uncompressed DVD/VOB LPCM audio decoder",
13 "dvdpcm",
14 "Nick Kurshev",
15 "A'rpi",
19 LIBAD_EXTERN(dvdpcm)
21 static int init(sh_audio_t *sh)
23 /* DVD PCM Audio:*/
24 sh->i_bps = 0;
25 if(sh->codecdata_len==3){
26 // we have LPCM header:
27 unsigned char h=sh->codecdata[1];
28 sh->channels=1+(h&7);
29 switch((h>>4)&3){
30 case 0: sh->samplerate=48000;break;
31 case 1: sh->samplerate=96000;break;
32 case 2: sh->samplerate=44100;break;
33 case 3: sh->samplerate=32000;break;
35 switch ((h >> 6) & 3) {
36 case 0:
37 sh->sample_format = AF_FORMAT_S16_BE;
38 sh->samplesize = 2;
39 break;
40 case 1:
41 mp_msg(MSGT_DECAUDIO, MSGL_INFO, MSGTR_SamplesWanted);
42 sh->i_bps = sh->channels * sh->samplerate * 5 / 2;
43 case 2:
44 sh->sample_format = AF_FORMAT_S24_BE;
45 sh->samplesize = 3;
46 break;
47 default:
48 sh->sample_format = AF_FORMAT_S16_BE;
49 sh->samplesize = 2;
51 } else {
52 // use defaults:
53 sh->channels=2;
54 sh->samplerate=48000;
55 sh->sample_format = AF_FORMAT_S16_BE;
56 sh->samplesize = 2;
58 if (!sh->i_bps)
59 sh->i_bps = sh->samplesize * sh->channels * sh->samplerate;
60 return 1;
63 static int preinit(sh_audio_t *sh)
65 sh->audio_out_minsize=2048;
66 return 1;
69 static void uninit(sh_audio_t *sh)
73 static int control(sh_audio_t *sh,int cmd,void* arg, ...)
75 int skip;
76 switch(cmd)
78 case ADCTRL_SKIP_FRAME:
79 skip=sh->i_bps/16;
80 skip=skip&(~3);
81 demux_read_data(sh->ds,NULL,skip);
82 return CONTROL_TRUE;
84 return CONTROL_UNKNOWN;
87 static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
89 int j,len;
90 if (sh_audio->samplesize == 3) {
91 if (((sh_audio->codecdata[1] >> 6) & 3) == 1) {
92 // 20 bit
93 // not sure if the "& 0xf0" and "<< 4" are the right way around
94 // can somebody clarify?
95 for (j = 0; j < minlen; j += 12) {
96 char tmp[10];
97 len = demux_read_data(sh_audio->ds, tmp, 10);
98 if (len < 10) break;
99 // first sample
100 buf[j + 0] = tmp[0];
101 buf[j + 1] = tmp[1];
102 buf[j + 2] = tmp[8] & 0xf0;
103 // second sample
104 buf[j + 3] = tmp[2];
105 buf[j + 4] = tmp[3];
106 buf[j + 5] = tmp[8] << 4;
107 // third sample
108 buf[j + 6] = tmp[4];
109 buf[j + 7] = tmp[5];
110 buf[j + 8] = tmp[9] & 0xf0;
111 // fourth sample
112 buf[j + 9] = tmp[6];
113 buf[j + 10] = tmp[7];
114 buf[j + 11] = tmp[9] << 4;
116 len = j;
117 } else {
118 // 24 bit
119 for (j = 0; j < minlen; j += 12) {
120 char tmp[12];
121 len = demux_read_data(sh_audio->ds, tmp, 12);
122 if (len < 12) break;
123 // first sample
124 buf[j + 0] = tmp[0];
125 buf[j + 1] = tmp[1];
126 buf[j + 2] = tmp[8];
127 // second sample
128 buf[j + 3] = tmp[2];
129 buf[j + 4] = tmp[3];
130 buf[j + 5] = tmp[9];
131 // third sample
132 buf[j + 6] = tmp[4];
133 buf[j + 7] = tmp[5];
134 buf[j + 8] = tmp[10];
135 // fourth sample
136 buf[j + 9] = tmp[6];
137 buf[j + 10] = tmp[7];
138 buf[j + 11] = tmp[11];
140 len = j;
142 } else
143 len=demux_read_data(sh_audio->ds,buf,(minlen+3)&(~3));
144 return len;