Mercurial > mplayer.hg
annotate libmpcodecs/ad_spdif.c @ 34583:8e4cafa03bd4
Cosmetic: Adjust indent.
author | ib |
---|---|
date | Thu, 09 Feb 2012 14:37:38 +0000 |
parents | 92841858c5cb |
children | f30c2707e168 |
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 { | |
85 const char *name; enum CodecID id; | |
86 } fmt_id_type[] = { | |
87 { "aac" , CODEC_ID_AAC }, | |
88 { "ac3" , CODEC_ID_AC3 }, | |
89 { "dca" , CODEC_ID_DTS }, | |
90 { "eac3", CODEC_ID_EAC3 }, | |
91 { "mpa" , CODEC_ID_MP3 }, | |
92 { "thd" , CODEC_ID_TRUEHD }, | |
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 bps = srate = 0; | |
141 x = ds_get_packet_pts(sh->ds, &start, &pts); | |
142 in_size = x; | |
143 if (x <= 0) { | |
144 pts = MP_NOPTS_VALUE; | |
145 x = 0; | |
146 } | |
147 ds_parse(sh->ds, &start, &x, pts, 0); | |
148 if (x == 0) { // not enough buffer | |
149 srate = 48000; //fake value | |
150 bps = 768000/8; //fake value | |
151 } else if (sh->avctx) { | |
152 if (sh->avctx->sample_rate < 44100) { | |
153 mp_msg(MSGT_DECAUDIO,MSGL_INFO, | |
154 "This stream sample_rate[%d Hz] may be broken. " | |
155 "Force reset 48000Hz.\n", | |
156 sh->avctx->sample_rate); | |
157 srate = 48000; //fake value | |
158 } else | |
159 srate = sh->avctx->sample_rate; | |
160 bps = sh->avctx->bit_rate/8; | |
161 } | |
162 sh->ds->buffer_pos -= in_size; | |
163 | |
164 switch (lavf_ctx->streams[0]->codec->codec_id) { | |
165 case CODEC_ID_AAC: | |
166 spdif_ctx->iec61937_packet_size = 16384; | |
167 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
168 sh->samplerate = srate; | |
169 sh->channels = 2; | |
170 sh->i_bps = bps; | |
171 break; | |
172 case CODEC_ID_AC3: | |
173 spdif_ctx->iec61937_packet_size = 6144; | |
174 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
175 sh->samplerate = srate; | |
176 sh->channels = 2; | |
177 sh->i_bps = bps; | |
178 break; | |
179 case CODEC_ID_DTS: // FORCE USE DTS-HD | |
180 opt = av_opt_find(&lavf_ctx->oformat->priv_class, | |
181 "dtshd_rate", NULL, 0, 0); | |
182 if (!opt) | |
183 goto fail; | |
184 dtshd_rate = (int*)(((uint8_t*)lavf_ctx->priv_data) + | |
185 opt->offset); | |
186 *dtshd_rate = 192000*4; | |
187 spdif_ctx->iec61937_packet_size = 32768; | |
188 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
189 sh->samplerate = 192000; // DTS core require 48000 | |
190 sh->channels = 2*4; | |
191 sh->i_bps = bps; | |
192 break; | |
193 case CODEC_ID_EAC3: | |
194 spdif_ctx->iec61937_packet_size = 24576; | |
195 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
196 sh->samplerate = 192000; | |
197 sh->channels = 2; | |
198 sh->i_bps = bps; | |
199 break; | |
200 case CODEC_ID_MP3: | |
201 spdif_ctx->iec61937_packet_size = 4608; | |
202 sh->sample_format = AF_FORMAT_MPEG2; | |
203 sh->samplerate = srate; | |
204 sh->channels = 2; | |
205 sh->i_bps = bps; | |
206 break; | |
207 case CODEC_ID_TRUEHD: | |
208 spdif_ctx->iec61937_packet_size = 61440; | |
209 sh->sample_format = AF_FORMAT_IEC61937_LE; | |
210 sh->samplerate = 192000; | |
211 sh->channels = 8; | |
212 sh->i_bps = bps; | |
213 break; | |
214 default: | |
215 break; | |
216 } | |
217 | |
218 return 1; | |
219 | |
220 fail: | |
221 uninit(sh); | |
222 return 0; | |
223 } | |
224 | |
225 static int decode_audio(sh_audio_t *sh, unsigned char *buf, | |
226 int minlen, int maxlen) | |
227 { | |
228 struct spdifContext *spdif_ctx = sh->context; | |
229 AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; | |
230 AVPacket pkt; | |
231 double pts; | |
232 int ret, in_size, consumed, x; | |
233 unsigned char *start = NULL; | |
234 | |
235 consumed = spdif_ctx->out_buffer_len = 0; | |
236 spdif_ctx->out_buffer_size = maxlen; | |
237 spdif_ctx->out_buffer = buf; | |
238 while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen | |
239 && spdif_ctx->out_buffer_len < minlen) { | |
240 if (sh->ds->eof) | |
241 break; | |
242 x = ds_get_packet_pts(sh->ds, &start, &pts); | |
243 if (x <= 0) { | |
244 x = 0; | |
245 ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0); | |
246 if (x == 0) | |
247 continue; // END_NOT_FOUND | |
248 in_size = x; | |
249 } else { | |
250 in_size = x; | |
251 consumed = ds_parse(sh->ds, &start, &x, pts, 0); | |
252 if (x == 0) { | |
253 mp_msg(MSGT_DECAUDIO,MSGL_V, | |
254 "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", | |
255 start, pkt.size, in_size, consumed, x); | |
256 continue; // END_NOT_FOUND | |
257 } | |
258 sh->ds->buffer_pos -= in_size - consumed; | |
259 } | |
260 av_init_packet(&pkt); | |
261 pkt.data = start; | |
262 pkt.size = x; | |
263 mp_msg(MSGT_DECAUDIO,MSGL_V, | |
264 "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", | |
265 start, pkt.size, in_size, consumed, x); | |
266 if (pts != MP_NOPTS_VALUE) { | |
267 sh->pts = pts; | |
268 sh->pts_bytes = 0; | |
269 } | |
270 ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); | |
271 if (ret < 0) | |
272 break; | |
273 } | |
274 sh->pts_bytes += spdif_ctx->out_buffer_len; | |
275 return spdif_ctx->out_buffer_len; | |
276 } | |
277 | |
278 static int control(sh_audio_t *sh, int cmd, void* arg, ...) | |
279 { | |
280 unsigned char *start; | |
281 double pts; | |
282 | |
283 switch (cmd) { | |
284 case ADCTRL_RESYNC_STREAM: | |
285 case ADCTRL_SKIP_FRAME: | |
286 ds_get_packet_pts(sh->ds, &start, &pts); | |
287 return CONTROL_TRUE; | |
288 } | |
289 return CONTROL_UNKNOWN; | |
290 } | |
291 | |
292 static void uninit(sh_audio_t *sh) | |
293 { | |
294 struct spdifContext *spdif_ctx = sh->context; | |
295 AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; | |
296 | |
297 if (lavf_ctx) { | |
298 if (lavf_ctx->oformat) | |
299 lavf_ctx->oformat->write_trailer(lavf_ctx); | |
300 av_freep(&lavf_ctx->pb); | |
301 if (lavf_ctx->streams) { | |
302 av_freep(&lavf_ctx->streams[0]->codec); | |
303 av_freep(&lavf_ctx->streams[0]->info); | |
304 av_freep(&lavf_ctx->streams[0]); | |
305 } | |
306 av_freep(&lavf_ctx->streams); | |
307 av_freep(&lavf_ctx->priv_data); | |
308 } | |
309 av_freep(&lavf_ctx); | |
310 av_freep(&spdif_ctx); | |
311 } |