Mercurial > mplayer.hg
annotate libmpcodecs/ad_spdif.c @ 36838:7df9dd22f234
Don't set win32 as audio driver if none has been given.
Select from the list of audio drivers instead.
Having win32 as selected item in the combo box although
this isn't used by MPlayer by default is confusing as well.
Besides that, there seem to be issues with this driver
when changing from or to it during playback.
author | ib |
---|---|
date | Tue, 25 Feb 2014 13:16:35 +0000 |
parents | 9b88b87f5921 |
children | 39b662840ac7 |
rev | line source |
---|---|
34103 | 1 /* |
2 * This file is part of MPlayer. | |
3 * | |
4 * MPlayer is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published by | |
6 * the Free Software Foundation; either version 2 of the License, or | |
7 * (at your option) any later version. | |
8 * | |
9 * MPlayer is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License along | |
15 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 */ | |
18 | |
19 #include <string.h> | |
20 | |
21 #include "config.h" | |
22 #include "mp_msg.h" | |
23 #include "ad_internal.h" | |
34206
92841858c5cb
Use init_avformat() instead of av_register_all().
cehoyos
parents:
34205
diff
changeset
|
24 #include "av_helpers.h" |
34103 | 25 #include "libavformat/avformat.h" |
26 #include "libavcodec/avcodec.h" | |
27 #include "libavutil/opt.h" | |
28 | |
29 static const ad_info_t info = { | |
30 "libavformat/spdifenc audio pass-through decoder.", | |
31 "spdif", | |
32 "Naoya OYAMA", | |
33 "Naoya OYAMA", | |
34 "For ALL hardware decoders" | |
35 }; | |
36 | |
37 LIBAD_EXTERN(spdif) | |
38 | |
39 #define FILENAME_SPDIFENC "spdif" | |
40 #define OUTBUF_SIZE 65536 | |
41 struct spdifContext { | |
42 AVFormatContext *lavf_ctx; | |
43 int iec61937_packet_size; | |
44 int out_buffer_len; | |
45 int out_buffer_size; | |
46 uint8_t *out_buffer; | |
47 uint8_t pb_buffer[OUTBUF_SIZE]; | |
48 }; | |
49 | |
50 static int read_packet(void *p, uint8_t *buf, int buf_size) | |
51 { | |
52 // spdifenc does not use read callback. | |
53 return 0; | |
54 } | |
55 | |
56 static int write_packet(void *p, uint8_t *buf, int buf_size) | |
57 { | |
58 int len; | |
59 struct spdifContext *ctx = p; | |
60 | |
61 len = FFMIN(buf_size, ctx->out_buffer_size -ctx->out_buffer_len); | |
62 memcpy(&ctx->out_buffer[ctx->out_buffer_len], buf, len); | |
63 ctx->out_buffer_len += len; | |
64 return len; | |
65 } | |
66 | |
67 static int64_t seek(void *p, int64_t offset, int whence) | |
68 { | |
69 // spdifenc does not use seek callback. | |
70 return 0; | |
71 } | |
72 | |
73 static int preinit(sh_audio_t *sh) | |
74 { | |
75 sh->samplesize = 2; | |
76 return 1; | |
77 } | |
78 | |
79 static int init(sh_audio_t *sh) | |
80 { | |
81 int i, x, in_size, srate, bps, *dtshd_rate; | |
82 unsigned char *start; | |
83 double pts; | |
84 static const struct { | |
35864 | 85 const char *name; enum AVCodecID id; |
34103 | 86 } fmt_id_type[] = { |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
87 { "aac" , AV_CODEC_ID_AAC }, |
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
88 { "ac3" , AV_CODEC_ID_AC3 }, |
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
89 { "dca" , AV_CODEC_ID_DTS }, |
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
90 { "eac3", AV_CODEC_ID_EAC3 }, |
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
91 { "mpa" , AV_CODEC_ID_MP3 }, |
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
92 { "thd" , AV_CODEC_ID_TRUEHD }, |
34103 | 93 { NULL , 0 } |
94 }; | |
95 AVFormatContext *lavf_ctx = NULL; | |
96 AVStream *stream = NULL; | |
97 const AVOption *opt = NULL; | |
98 struct spdifContext *spdif_ctx = NULL; | |
99 | |
100 spdif_ctx = av_mallocz(sizeof(*spdif_ctx)); | |
101 if (!spdif_ctx) | |
102 goto fail; | |
103 spdif_ctx->lavf_ctx = avformat_alloc_context(); | |
104 if (!spdif_ctx->lavf_ctx) | |
105 goto fail; | |
106 | |
107 sh->context = spdif_ctx; | |
108 lavf_ctx = spdif_ctx->lavf_ctx; | |
109 | |
34206
92841858c5cb
Use init_avformat() instead of av_register_all().
cehoyos
parents:
34205
diff
changeset
|
110 init_avformat(); |
34103 | 111 lavf_ctx->oformat = av_guess_format(FILENAME_SPDIFENC, NULL, NULL); |
112 if (!lavf_ctx->oformat) | |
113 goto fail; | |
114 lavf_ctx->priv_data = av_mallocz(lavf_ctx->oformat->priv_data_size); | |
115 if (!lavf_ctx->priv_data) | |
116 goto fail; | |
117 lavf_ctx->pb = avio_alloc_context(spdif_ctx->pb_buffer, OUTBUF_SIZE, 1, spdif_ctx, | |
118 read_packet, write_packet, seek); | |
119 if (!lavf_ctx->pb) | |
120 goto fail; | |
34204
c1b5018b5edb
Use new API avformat_new_stream() instead of the deprecated
cehoyos
parents:
34203
diff
changeset
|
121 stream = avformat_new_stream(lavf_ctx, 0); |
34103 | 122 if (!stream) |
123 goto fail; | |
124 lavf_ctx->duration = AV_NOPTS_VALUE; | |
125 lavf_ctx->start_time = AV_NOPTS_VALUE; | |
126 for (i = 0; fmt_id_type[i].name; i++) { | |
127 if (!strcmp(sh->codec->dll, fmt_id_type[i].name)) { | |
128 lavf_ctx->streams[0]->codec->codec_id = fmt_id_type[i].id; | |
129 break; | |
130 } | |
131 } | |
132 lavf_ctx->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; | |
133 if (AVERROR_PATCHWELCOME == lavf_ctx->oformat->write_header(lavf_ctx)) { | |
134 mp_msg(MSGT_DECAUDIO,MSGL_INFO, | |
135 "This codec is not supported by spdifenc.\n"); | |
136 goto fail; | |
137 } | |
138 | |
139 // get sample_rate & bitrate from parser | |
140 x = ds_get_packet_pts(sh->ds, &start, &pts); | |
141 in_size = x; | |
142 if (x <= 0) { | |
143 pts = MP_NOPTS_VALUE; | |
144 x = 0; | |
145 } | |
146 ds_parse(sh->ds, &start, &x, pts, 0); | |
35423
eef7c4527712
Do not fall back to 0 for samplerate when parser is not initialized.
reimar
parents:
35306
diff
changeset
|
147 srate = 48000; //fake value |
eef7c4527712
Do not fall back to 0 for samplerate when parser is not initialized.
reimar
parents:
35306
diff
changeset
|
148 bps = 768000/8; //fake value |
eef7c4527712
Do not fall back to 0 for samplerate when parser is not initialized.
reimar
parents:
35306
diff
changeset
|
149 if (x && sh->avctx) { // we have parser and large enough buffer |
34103 | 150 if (sh->avctx->sample_rate < 44100) { |
151 mp_msg(MSGT_DECAUDIO,MSGL_INFO, | |
152 "This stream sample_rate[%d Hz] may be broken. " | |
153 "Force reset 48000Hz.\n", | |
154 sh->avctx->sample_rate); | |
155 srate = 48000; //fake value | |
156 } else | |
157 srate = sh->avctx->sample_rate; | |
158 bps = sh->avctx->bit_rate/8; | |
159 } | |
160 sh->ds->buffer_pos -= in_size; | |
161 | |
162 switch (lavf_ctx->streams[0]->codec->codec_id) { | |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
163 case AV_CODEC_ID_AAC: |
34103 | 164 spdif_ctx->iec61937_packet_size = 16384; |
165 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
166 sh->samplerate = srate; | |
167 sh->channels = 2; | |
168 sh->i_bps = bps; | |
169 break; | |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
170 case AV_CODEC_ID_AC3: |
34103 | 171 spdif_ctx->iec61937_packet_size = 6144; |
35442
2b45dfcde03c
ad_spdif: use the more specific AF_FORMAT_AC3_LE when
reimar
parents:
35423
diff
changeset
|
172 sh->sample_format = AF_FORMAT_AC3_LE; |
34103 | 173 sh->samplerate = srate; |
174 sh->channels = 2; | |
175 sh->i_bps = bps; | |
176 break; | |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
177 case AV_CODEC_ID_DTS: // FORCE USE DTS-HD |
34103 | 178 opt = av_opt_find(&lavf_ctx->oformat->priv_class, |
179 "dtshd_rate", NULL, 0, 0); | |
180 if (!opt) | |
181 goto fail; | |
182 dtshd_rate = (int*)(((uint8_t*)lavf_ctx->priv_data) + | |
183 opt->offset); | |
184 *dtshd_rate = 192000*4; | |
185 spdif_ctx->iec61937_packet_size = 32768; | |
186 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
187 sh->samplerate = 192000; // DTS core require 48000 | |
188 sh->channels = 2*4; | |
189 sh->i_bps = bps; | |
190 break; | |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
191 case AV_CODEC_ID_EAC3: |
34103 | 192 spdif_ctx->iec61937_packet_size = 24576; |
193 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
194 sh->samplerate = 192000; | |
195 sh->channels = 2; | |
196 sh->i_bps = bps; | |
197 break; | |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
198 case AV_CODEC_ID_MP3: |
34103 | 199 spdif_ctx->iec61937_packet_size = 4608; |
200 sh->sample_format = AF_FORMAT_MPEG2; | |
201 sh->samplerate = srate; | |
202 sh->channels = 2; | |
203 sh->i_bps = bps; | |
204 break; | |
35715
8517826b0dbd
Replace CODEC_IDs their modern AV_-prefixed counterparts.
diego
parents:
35442
diff
changeset
|
205 case AV_CODEC_ID_TRUEHD: |
34103 | 206 spdif_ctx->iec61937_packet_size = 61440; |
207 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
208 sh->samplerate = 192000; | |
209 sh->channels = 8; | |
210 sh->i_bps = bps; | |
211 break; | |
212 default: | |
213 break; | |
214 } | |
215 | |
216 return 1; | |
217 | |
218 fail: | |
219 uninit(sh); | |
220 return 0; | |
221 } | |
222 | |
223 static int decode_audio(sh_audio_t *sh, unsigned char *buf, | |
224 int minlen, int maxlen) | |
225 { | |
226 struct spdifContext *spdif_ctx = sh->context; | |
227 AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; | |
228 AVPacket pkt; | |
229 double pts; | |
230 int ret, in_size, consumed, x; | |
231 unsigned char *start = NULL; | |
232 | |
233 consumed = spdif_ctx->out_buffer_len = 0; | |
234 spdif_ctx->out_buffer_size = maxlen; | |
235 spdif_ctx->out_buffer = buf; | |
236 while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen | |
237 && spdif_ctx->out_buffer_len < minlen) { | |
238 if (sh->ds->eof) | |
239 break; | |
240 x = ds_get_packet_pts(sh->ds, &start, &pts); | |
241 if (x <= 0) { | |
242 x = 0; | |
243 ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0); | |
244 if (x == 0) | |
245 continue; // END_NOT_FOUND | |
246 in_size = x; | |
247 } else { | |
248 in_size = x; | |
249 consumed = ds_parse(sh->ds, &start, &x, pts, 0); | |
250 if (x == 0) { | |
251 mp_msg(MSGT_DECAUDIO,MSGL_V, | |
252 "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", | |
35306
f30c2707e168
Do not use pkt which is uninitialized at that point.
reimar
parents:
34206
diff
changeset
|
253 start, 0, in_size, consumed, x); |
34103 | 254 continue; // END_NOT_FOUND |
255 } | |
256 sh->ds->buffer_pos -= in_size - consumed; | |
257 } | |
258 av_init_packet(&pkt); | |
259 pkt.data = start; | |
260 pkt.size = x; | |
261 mp_msg(MSGT_DECAUDIO,MSGL_V, | |
262 "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", | |
263 start, pkt.size, in_size, consumed, x); | |
264 if (pts != MP_NOPTS_VALUE) { | |
265 sh->pts = pts; | |
266 sh->pts_bytes = 0; | |
267 } | |
268 ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); | |
269 if (ret < 0) | |
270 break; | |
271 } | |
272 sh->pts_bytes += spdif_ctx->out_buffer_len; | |
273 return spdif_ctx->out_buffer_len; | |
274 } | |
275 | |
276 static int control(sh_audio_t *sh, int cmd, void* arg, ...) | |
277 { | |
278 unsigned char *start; | |
279 double pts; | |
280 | |
281 switch (cmd) { | |
282 case ADCTRL_RESYNC_STREAM: | |
283 case ADCTRL_SKIP_FRAME: | |
284 ds_get_packet_pts(sh->ds, &start, &pts); | |
285 return CONTROL_TRUE; | |
286 } | |
287 return CONTROL_UNKNOWN; | |
288 } | |
289 | |
290 static void uninit(sh_audio_t *sh) | |
291 { | |
292 struct spdifContext *spdif_ctx = sh->context; | |
293 AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; | |
294 | |
295 if (lavf_ctx) { | |
296 if (lavf_ctx->oformat) | |
297 lavf_ctx->oformat->write_trailer(lavf_ctx); | |
298 av_freep(&lavf_ctx->pb); | |
299 if (lavf_ctx->streams) { | |
300 av_freep(&lavf_ctx->streams[0]->codec); | |
301 av_freep(&lavf_ctx->streams[0]->info); | |
302 av_freep(&lavf_ctx->streams[0]); | |
303 } | |
304 av_freep(&lavf_ctx->streams); | |
305 av_freep(&lavf_ctx->priv_data); | |
306 } | |
307 av_freep(&lavf_ctx); | |
308 av_freep(&spdif_ctx); | |
309 } |