Mercurial > mplayer.hg
annotate libmpcodecs/ad_spdif.c @ 34203:362c9229e16e
Call av_register_all() before initialising the SPDIF muxer.
Fixes playback with -demuxer mpegts -ac spdifac3.
Patch by Naoya OYAMA, naoya D oyama gmail
author | cehoyos |
---|---|
date | Thu, 03 Nov 2011 18:43:49 +0000 |
parents | febe300dbfc0 |
children | c1b5018b5edb |
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" | |
24 #include "libavformat/avformat.h" | |
25 #include "libavcodec/avcodec.h" | |
26 #include "libavutil/opt.h" | |
27 | |
28 static const ad_info_t info = { | |
29 "libavformat/spdifenc audio pass-through decoder.", | |
30 "spdif", | |
31 "Naoya OYAMA", | |
32 "Naoya OYAMA", | |
33 "For ALL hardware decoders" | |
34 }; | |
35 | |
36 LIBAD_EXTERN(spdif) | |
37 | |
38 #define FILENAME_SPDIFENC "spdif" | |
39 #define OUTBUF_SIZE 65536 | |
40 struct spdifContext { | |
41 AVFormatContext *lavf_ctx; | |
42 int iec61937_packet_size; | |
43 int out_buffer_len; | |
44 int out_buffer_size; | |
45 uint8_t *out_buffer; | |
46 uint8_t pb_buffer[OUTBUF_SIZE]; | |
47 }; | |
48 | |
49 static int read_packet(void *p, uint8_t *buf, int buf_size) | |
50 { | |
51 // spdifenc does not use read callback. | |
52 return 0; | |
53 } | |
54 | |
55 static int write_packet(void *p, uint8_t *buf, int buf_size) | |
56 { | |
57 int len; | |
58 struct spdifContext *ctx = p; | |
59 | |
60 len = FFMIN(buf_size, ctx->out_buffer_size -ctx->out_buffer_len); | |
61 memcpy(&ctx->out_buffer[ctx->out_buffer_len], buf, len); | |
62 ctx->out_buffer_len += len; | |
63 return len; | |
64 } | |
65 | |
66 static int64_t seek(void *p, int64_t offset, int whence) | |
67 { | |
68 // spdifenc does not use seek callback. | |
69 return 0; | |
70 } | |
71 | |
72 static int preinit(sh_audio_t *sh) | |
73 { | |
74 sh->samplesize = 2; | |
75 return 1; | |
76 } | |
77 | |
78 static int init(sh_audio_t *sh) | |
79 { | |
80 int i, x, in_size, srate, bps, *dtshd_rate; | |
81 unsigned char *start; | |
82 double pts; | |
83 static const struct { | |
84 const char *name; enum CodecID id; | |
85 } fmt_id_type[] = { | |
86 { "aac" , CODEC_ID_AAC }, | |
87 { "ac3" , CODEC_ID_AC3 }, | |
88 { "dca" , CODEC_ID_DTS }, | |
89 { "eac3", CODEC_ID_EAC3 }, | |
90 { "mpa" , CODEC_ID_MP3 }, | |
91 { "thd" , CODEC_ID_TRUEHD }, | |
92 { NULL , 0 } | |
93 }; | |
94 AVFormatContext *lavf_ctx = NULL; | |
95 AVStream *stream = NULL; | |
96 const AVOption *opt = NULL; | |
97 struct spdifContext *spdif_ctx = NULL; | |
98 | |
99 spdif_ctx = av_mallocz(sizeof(*spdif_ctx)); | |
100 if (!spdif_ctx) | |
101 goto fail; | |
102 spdif_ctx->lavf_ctx = avformat_alloc_context(); | |
103 if (!spdif_ctx->lavf_ctx) | |
104 goto fail; | |
105 | |
106 sh->context = spdif_ctx; | |
107 lavf_ctx = spdif_ctx->lavf_ctx; | |
108 | |
34203
362c9229e16e
Call av_register_all() before initialising the SPDIF muxer.
cehoyos
parents:
34103
diff
changeset
|
109 av_register_all(); |
34103 | 110 lavf_ctx->oformat = av_guess_format(FILENAME_SPDIFENC, NULL, NULL); |
111 if (!lavf_ctx->oformat) | |
112 goto fail; | |
113 lavf_ctx->priv_data = av_mallocz(lavf_ctx->oformat->priv_data_size); | |
114 if (!lavf_ctx->priv_data) | |
115 goto fail; | |
116 lavf_ctx->pb = avio_alloc_context(spdif_ctx->pb_buffer, OUTBUF_SIZE, 1, spdif_ctx, | |
117 read_packet, write_packet, seek); | |
118 if (!lavf_ctx->pb) | |
119 goto fail; | |
120 stream = av_new_stream(lavf_ctx, 0); | |
121 if (!stream) | |
122 goto fail; | |
123 lavf_ctx->duration = AV_NOPTS_VALUE; | |
124 lavf_ctx->start_time = AV_NOPTS_VALUE; | |
125 for (i = 0; fmt_id_type[i].name; i++) { | |
126 if (!strcmp(sh->codec->dll, fmt_id_type[i].name)) { | |
127 lavf_ctx->streams[0]->codec->codec_id = fmt_id_type[i].id; | |
128 break; | |
129 } | |
130 } | |
131 lavf_ctx->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; | |
132 if (AVERROR_PATCHWELCOME == lavf_ctx->oformat->write_header(lavf_ctx)) { | |
133 mp_msg(MSGT_DECAUDIO,MSGL_INFO, | |
134 "This codec is not supported by spdifenc.\n"); | |
135 goto fail; | |
136 } | |
137 | |
138 // get sample_rate & bitrate from parser | |
139 bps = srate = 0; | |
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); | |
147 if (x == 0) { // not enough buffer | |
148 srate = 48000; //fake value | |
149 bps = 768000/8; //fake value | |
150 } else if (sh->avctx) { | |
151 if (sh->avctx->sample_rate < 44100) { | |
152 mp_msg(MSGT_DECAUDIO,MSGL_INFO, | |
153 "This stream sample_rate[%d Hz] may be broken. " | |
154 "Force reset 48000Hz.\n", | |
155 sh->avctx->sample_rate); | |
156 srate = 48000; //fake value | |
157 } else | |
158 srate = sh->avctx->sample_rate; | |
159 bps = sh->avctx->bit_rate/8; | |
160 } else { | |
161 ; | |
162 } | |
163 sh->ds->buffer_pos -= in_size; | |
164 | |
165 switch (lavf_ctx->streams[0]->codec->codec_id) { | |
166 case CODEC_ID_AAC: | |
167 spdif_ctx->iec61937_packet_size = 16384; | |
168 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
169 sh->samplerate = srate; | |
170 sh->channels = 2; | |
171 sh->i_bps = bps; | |
172 break; | |
173 case CODEC_ID_AC3: | |
174 spdif_ctx->iec61937_packet_size = 6144; | |
175 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
176 sh->samplerate = srate; | |
177 sh->channels = 2; | |
178 sh->i_bps = bps; | |
179 break; | |
180 case CODEC_ID_DTS: // FORCE USE DTS-HD | |
181 opt = av_opt_find(&lavf_ctx->oformat->priv_class, | |
182 "dtshd_rate", NULL, 0, 0); | |
183 if (!opt) | |
184 goto fail; | |
185 dtshd_rate = (int*)(((uint8_t*)lavf_ctx->priv_data) + | |
186 opt->offset); | |
187 *dtshd_rate = 192000*4; | |
188 spdif_ctx->iec61937_packet_size = 32768; | |
189 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
190 sh->samplerate = 192000; // DTS core require 48000 | |
191 sh->channels = 2*4; | |
192 sh->i_bps = bps; | |
193 break; | |
194 case CODEC_ID_EAC3: | |
195 spdif_ctx->iec61937_packet_size = 24576; | |
196 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
197 sh->samplerate = 192000; | |
198 sh->channels = 2; | |
199 sh->i_bps = bps; | |
200 break; | |
201 case CODEC_ID_MP3: | |
202 spdif_ctx->iec61937_packet_size = 4608; | |
203 sh->sample_format = AF_FORMAT_MPEG2; | |
204 sh->samplerate = srate; | |
205 sh->channels = 2; | |
206 sh->i_bps = bps; | |
207 break; | |
208 case CODEC_ID_TRUEHD: | |
209 spdif_ctx->iec61937_packet_size = 61440; | |
210 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
211 sh->samplerate = 192000; | |
212 sh->channels = 8; | |
213 sh->i_bps = bps; | |
214 break; | |
215 default: | |
216 break; | |
217 } | |
218 | |
219 return 1; | |
220 | |
221 fail: | |
222 uninit(sh); | |
223 return 0; | |
224 } | |
225 | |
226 static int decode_audio(sh_audio_t *sh, unsigned char *buf, | |
227 int minlen, int maxlen) | |
228 { | |
229 struct spdifContext *spdif_ctx = sh->context; | |
230 AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; | |
231 AVPacket pkt; | |
232 double pts; | |
233 int ret, in_size, consumed, x; | |
234 unsigned char *start = NULL; | |
235 | |
236 consumed = spdif_ctx->out_buffer_len = 0; | |
237 spdif_ctx->out_buffer_size = maxlen; | |
238 spdif_ctx->out_buffer = buf; | |
239 while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen | |
240 && spdif_ctx->out_buffer_len < minlen) { | |
241 if (sh->ds->eof) | |
242 break; | |
243 x = ds_get_packet_pts(sh->ds, &start, &pts); | |
244 if (x <= 0) { | |
245 x = 0; | |
246 ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0); | |
247 if (x == 0) | |
248 continue; // END_NOT_FOUND | |
249 in_size = x; | |
250 } else { | |
251 in_size = x; | |
252 consumed = ds_parse(sh->ds, &start, &x, pts, 0); | |
253 if (x == 0) { | |
254 mp_msg(MSGT_DECAUDIO,MSGL_V, | |
255 "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", | |
256 start, pkt.size, in_size, consumed, x); | |
257 continue; // END_NOT_FOUND | |
258 } | |
259 sh->ds->buffer_pos -= in_size - consumed; | |
260 } | |
261 av_init_packet(&pkt); | |
262 pkt.data = start; | |
263 pkt.size = x; | |
264 mp_msg(MSGT_DECAUDIO,MSGL_V, | |
265 "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", | |
266 start, pkt.size, in_size, consumed, x); | |
267 if (pts != MP_NOPTS_VALUE) { | |
268 sh->pts = pts; | |
269 sh->pts_bytes = 0; | |
270 } | |
271 ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); | |
272 if (ret < 0) | |
273 break; | |
274 } | |
275 sh->pts_bytes += spdif_ctx->out_buffer_len; | |
276 return spdif_ctx->out_buffer_len; | |
277 } | |
278 | |
279 static int control(sh_audio_t *sh, int cmd, void* arg, ...) | |
280 { | |
281 unsigned char *start; | |
282 double pts; | |
283 | |
284 switch (cmd) { | |
285 case ADCTRL_RESYNC_STREAM: | |
286 case ADCTRL_SKIP_FRAME: | |
287 ds_get_packet_pts(sh->ds, &start, &pts); | |
288 return CONTROL_TRUE; | |
289 } | |
290 return CONTROL_UNKNOWN; | |
291 } | |
292 | |
293 static void uninit(sh_audio_t *sh) | |
294 { | |
295 struct spdifContext *spdif_ctx = sh->context; | |
296 AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; | |
297 | |
298 if (lavf_ctx) { | |
299 if (lavf_ctx->oformat) | |
300 lavf_ctx->oformat->write_trailer(lavf_ctx); | |
301 av_freep(&lavf_ctx->pb); | |
302 if (lavf_ctx->streams) { | |
303 av_freep(&lavf_ctx->streams[0]->codec); | |
304 av_freep(&lavf_ctx->streams[0]->info); | |
305 av_freep(&lavf_ctx->streams[0]); | |
306 } | |
307 av_freep(&lavf_ctx->streams); | |
308 av_freep(&lavf_ctx->priv_data); | |
309 } | |
310 av_freep(&lavf_ctx); | |
311 av_freep(&spdif_ctx); | |
312 } |