Mercurial > mplayer.hg
annotate libmpdemux/demux_nut.c @ 35023:6077de703cf4
When switching programs select subtitle stream regardless of
whether the format is text, ASS, bitmap or whatever.
There probably was some good reason for the condition but
it got lost in time and special-casing CODEC_ID_TEXT over other
test-based subtitles doesn't seem to make much sense.
author | reimar |
---|---|
date | Sat, 25 Aug 2012 10:50:50 +0000 |
parents | a86413775fbe |
children | 139f2b064ef9 |
rev | line source |
---|---|
29238
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
1 /* |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
2 * This file is part of MPlayer. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
3 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
4 * MPlayer is free software; you can redistribute it and/or modify |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
5 * it under the terms of the GNU General Public License as published by |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
6 * the Free Software Foundation; either version 2 of the License, or |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
7 * (at your option) any later version. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
8 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
9 * MPlayer is distributed in the hope that it will be useful, |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
12 * GNU General Public License for more details. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
13 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
14 * You should have received a copy of the GNU General Public License along |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
15 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
17 */ |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28101
diff
changeset
|
18 |
19861 | 19 #include <stdio.h> |
20815 | 20 #include <stdlib.h> |
19861 | 21 |
22 #include "config.h" | |
23 #include "mp_msg.h" | |
24 | |
23084 | 25 #include "help_mp.h" |
26 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
22484
diff
changeset
|
27 #include "stream/stream.h" |
19861 | 28 #include "demuxer.h" |
29 #include "stheader.h" | |
30 | |
20893 | 31 #include <libnut.h> |
19861 | 32 |
33 typedef struct { | |
34 int last_pts; // FIXME | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
35 nut_context_tt * nut; |
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
36 nut_stream_header_tt * s; |
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
37 } nut_priv_tt; |
19861 | 38 |
39 static size_t mp_read(void * h, size_t len, uint8_t * buf) { | |
40 stream_t * stream = (stream_t*)h; | |
41 | |
42 if(stream_eof(stream)) return 0; | |
21022 | 43 //len = MIN(len, 5); |
19861 | 44 |
45 return stream_read(stream, buf, len); | |
46 } | |
47 | |
21022 | 48 static int mp_eof(void * h) { |
49 stream_t * stream = (stream_t*)h; | |
50 if(stream_eof(stream)) return 1; | |
51 return 0; | |
52 } | |
53 | |
19861 | 54 static off_t mp_seek(void * h, long long pos, int whence) { |
55 stream_t * stream = (stream_t*)h; | |
56 | |
57 if (stream->end_pos < stream_tell(stream)) | |
58 stream->end_pos = stream_tell(stream); | |
59 | |
60 if (whence == SEEK_CUR) pos += stream_tell(stream); | |
61 else if (whence == SEEK_END) pos += stream->end_pos; | |
62 else if (whence != SEEK_SET) return -1; | |
63 | |
64 if (pos < stream->end_pos && stream->eof) stream_reset(stream); | |
65 if (stream_seek(stream, pos) == 0) return -1; | |
66 | |
67 return pos; | |
68 } | |
69 | |
70 #define ID_STRING "nut/multimedia container" | |
71 #define ID_LENGTH (strlen(ID_STRING) + 1) | |
72 | |
73 static int nut_check_file(demuxer_t * demuxer) { | |
74 uint8_t buf[ID_LENGTH]; | |
75 | |
76 if (stream_read(demuxer->stream, buf, ID_LENGTH) != ID_LENGTH) return 0; | |
77 | |
78 if (memcmp(buf, ID_STRING, ID_LENGTH)) return 0; | |
79 | |
80 stream_seek(demuxer->stream, 0); | |
81 return DEMUXER_TYPE_NUT; | |
82 } | |
83 | |
84 static demuxer_t * demux_open_nut(demuxer_t * demuxer) { | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
85 nut_demuxer_opts_tt dopts = { |
19861 | 86 .input = { |
87 .priv = demuxer->stream, | |
88 .seek = mp_seek, | |
89 .read = mp_read, | |
21022 | 90 .eof = mp_eof, |
19861 | 91 .file_pos = stream_tell(demuxer->stream), |
92 }, | |
19957 | 93 .alloc = { .malloc = NULL }, |
20909 | 94 .read_index = index_mode, |
95 .cache_syncpoints = 1, | |
19861 | 96 }; |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
97 nut_priv_tt * priv = demuxer->priv = calloc(1, sizeof(nut_priv_tt)); |
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
98 nut_context_tt * nut = priv->nut = nut_demuxer_init(&dopts); |
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
99 nut_stream_header_tt * s; |
19861 | 100 int ret; |
101 int i; | |
102 | |
21022 | 103 while ((ret = nut_read_headers(nut, &s, NULL)) == NUT_ERR_EAGAIN); |
104 if (ret) { | |
20938 | 105 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret)); |
19861 | 106 return NULL; |
107 } | |
108 | |
109 priv->s = s; | |
110 | |
111 for (i = 0; s[i].type != -1 && i < 2; i++) switch(s[i].type) { | |
112 case NUT_AUDIO_CLASS: { | |
113 WAVEFORMATEX *wf = | |
32121 | 114 calloc(sizeof(*wf) + |
19861 | 115 s[i].codec_specific_len, 1); |
31609
cd81fce1f010
Make the stream language an argument to the stream creation function
reimar
parents:
29238
diff
changeset
|
116 sh_audio_t* sh_audio = new_sh_audio(demuxer, i, NULL); |
28101 | 117 int j; |
23010
74efb0fa8a0b
with -identify show audio and video id; patch by Andrew Savchenko (Bircoph list ru)
nicodvb
parents:
22605
diff
changeset
|
118 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "nut", i); |
19861 | 119 |
120 sh_audio->wf= wf; sh_audio->ds = demuxer->audio; | |
121 sh_audio->audio.dwSampleSize = 0; // FIXME | |
21723 | 122 sh_audio->audio.dwScale = s[i].time_base.num; |
19861 | 123 sh_audio->audio.dwRate = s[i].time_base.den; |
124 sh_audio->format = 0; | |
125 for (j = 0; j < s[i].fourcc_len && j < 4; j++) | |
126 sh_audio->format |= s[i].fourcc[j]<<(j*8); | |
127 sh_audio->channels = s[i].channel_count; | |
128 sh_audio->samplerate = | |
21723 | 129 s[i].samplerate_num / s[i].samplerate_denom; |
19861 | 130 sh_audio->i_bps = 0; // FIXME |
131 | |
132 wf->wFormatTag = sh_audio->format; | |
133 wf->nChannels = s[i].channel_count; | |
134 wf->nSamplesPerSec = | |
21723 | 135 s[i].samplerate_num / s[i].samplerate_denom; |
19861 | 136 wf->nAvgBytesPerSec = 0; // FIXME |
137 wf->nBlockAlign = 0; // FIXME | |
138 wf->wBitsPerSample = 0; // FIXME | |
139 wf->cbSize = s[i].codec_specific_len; | |
140 if (s[i].codec_specific_len) | |
141 memcpy(wf + 1, s[i].codec_specific, | |
142 s[i].codec_specific_len); | |
143 | |
144 demuxer->audio->id = i; | |
145 demuxer->audio->sh= demuxer->a_streams[i]; | |
146 break; | |
147 } | |
148 case NUT_VIDEO_CLASS: { | |
149 BITMAPINFOHEADER * bih = | |
32123 | 150 calloc(sizeof(*bih) + |
19861 | 151 s[i].codec_specific_len, 1); |
152 sh_video_t * sh_video = new_sh_video(demuxer, i); | |
28101 | 153 int j; |
23010
74efb0fa8a0b
with -identify show audio and video id; patch by Andrew Savchenko (Bircoph list ru)
nicodvb
parents:
22605
diff
changeset
|
154 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "nut", i); |
19861 | 155 |
156 sh_video->bih = bih; | |
157 sh_video->ds = demuxer->video; | |
158 sh_video->disp_w = s[i].width; | |
159 sh_video->disp_h = s[i].height; | |
21723 | 160 sh_video->video.dwScale = s[i].time_base.num; |
19861 | 161 sh_video->video.dwRate = s[i].time_base.den; |
162 | |
163 sh_video->fps = sh_video->video.dwRate/ | |
164 (float)sh_video->video.dwScale; | |
165 sh_video->frametime = 1./sh_video->fps; | |
166 sh_video->format = 0; | |
167 for (j = 0; j < s[i].fourcc_len && j < 4; j++) | |
168 sh_video->format |= s[i].fourcc[j]<<(j*8); | |
169 if (!s[i].sample_height) sh_video->aspect = 0; | |
170 else sh_video->aspect = | |
171 s[i].sample_width / (float)s[i].sample_height; | |
172 sh_video->i_bps = 0; // FIXME | |
173 | |
32123 | 174 bih->biSize = sizeof(*bih) + |
19861 | 175 s[i].codec_specific_len; |
176 bih->biWidth = s[i].width; | |
177 bih->biHeight = s[i].height; | |
178 bih->biBitCount = 0; // FIXME | |
179 bih->biSizeImage = 0; // FIXME | |
180 bih->biCompression = sh_video->format; | |
181 | |
182 if (s[i].codec_specific_len) | |
183 memcpy(bih + 1, s[i].codec_specific, | |
184 s[i].codec_specific_len); | |
185 | |
186 demuxer->video->id = i; | |
187 demuxer->video->sh = demuxer->v_streams[i]; | |
188 break; | |
189 } | |
190 } | |
191 | |
192 return demuxer; | |
193 } | |
194 | |
195 static int demux_nut_fill_buffer(demuxer_t * demuxer, demux_stream_t * dsds) { | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
196 nut_priv_tt * priv = demuxer->priv; |
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
197 nut_context_tt * nut = priv->nut; |
19861 | 198 demux_packet_t *dp; |
199 demux_stream_t *ds; | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
200 nut_packet_tt pd; |
19861 | 201 int ret; |
202 double pts; | |
203 | |
204 demuxer->filepos = stream_tell(demuxer->stream); | |
205 if (stream_eof(demuxer->stream)) return 0; | |
206 | |
21022 | 207 while ((ret = nut_read_next_packet(nut, &pd)) == NUT_ERR_EAGAIN); |
20938 | 208 if (ret) { |
209 if (ret != NUT_ERR_EOF) | |
210 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", | |
211 nut_error(ret)); | |
212 return 0; // fatal error | |
19861 | 213 } |
214 | |
21723 | 215 pts = (double)pd.pts * priv->s[pd.stream].time_base.num / |
19861 | 216 priv->s[pd.stream].time_base.den; |
217 | |
218 if (pd.stream == demuxer->audio->id) { | |
219 ds = demuxer->audio; | |
220 } | |
221 else if (pd.stream == demuxer->video->id) { | |
222 ds = demuxer->video; | |
223 } | |
224 else { | |
20926 | 225 uint8_t buf[pd.len]; |
21022 | 226 while ((ret = nut_read_frame(nut, &pd.len, buf)) == NUT_ERR_EAGAIN); |
20938 | 227 if (ret) { |
19958 | 228 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", |
20938 | 229 nut_error(ret)); |
230 return 0; // fatal error | |
19861 | 231 } |
232 return 1; | |
233 } | |
234 | |
235 if (pd.stream == 0) priv->last_pts = pd.pts; | |
236 | |
237 dp = new_demux_packet(pd.len); | |
238 | |
239 dp->pts = pts; | |
240 | |
241 dp->pos = demuxer->filepos; | |
242 dp->flags= (pd.flags & NUT_FLAG_KEY) ? 0x10 : 0; | |
243 | |
21022 | 244 {int len = pd.len; |
245 while ((ret = nut_read_frame(nut, &len, dp->buffer + pd.len-len)) == NUT_ERR_EAGAIN); | |
246 } | |
20938 | 247 if (ret) { |
19958 | 248 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", |
20938 | 249 nut_error(ret)); |
250 return 0; // fatal error | |
19861 | 251 } |
19958 | 252 |
19861 | 253 ds_add_packet(ds, dp); // append packet to DS stream |
254 return 1; | |
255 } | |
256 | |
257 static void demux_seek_nut(demuxer_t * demuxer, float time_pos, float audio_delay, int flags) { | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
258 nut_context_tt * nut = ((nut_priv_tt*)demuxer->priv)->nut; |
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
259 nut_priv_tt * priv = demuxer->priv; |
19861 | 260 int nutflags = 0; |
261 int ret; | |
262 const int tmp[] = { 0, -1 }; | |
263 | |
25883
baf32110d3fc
Use defines to give names to the different seek flags.
reimar
parents:
25707
diff
changeset
|
264 if (!(flags & SEEK_ABSOLUTE)) { |
19861 | 265 nutflags |= 1; // relative |
266 if (time_pos > 0) nutflags |= 2; // forwards | |
267 } | |
268 | |
25883
baf32110d3fc
Use defines to give names to the different seek flags.
reimar
parents:
25707
diff
changeset
|
269 if (flags & SEEK_FACTOR) |
19861 | 270 time_pos *= priv->s[0].max_pts * |
21723 | 271 (double)priv->s[0].time_base.num / |
19861 | 272 priv->s[0].time_base.den; |
273 | |
21022 | 274 while ((ret = nut_seek(nut, time_pos, nutflags, tmp)) == NUT_ERR_EAGAIN); |
21023
f5180197d7ad
fix demux_nut to give proper (estimate) of percent position after a seek
ods15
parents:
21022
diff
changeset
|
275 priv->last_pts = -1; |
20971
e243a3de18c2
missed piece in update to libnut API - non negative errors
ods15
parents:
20938
diff
changeset
|
276 if (ret) mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret)); |
21023
f5180197d7ad
fix demux_nut to give proper (estimate) of percent position after a seek
ods15
parents:
21022
diff
changeset
|
277 demuxer->filepos = stream_tell(demuxer->stream); |
19861 | 278 } |
279 | |
280 static int demux_control_nut(demuxer_t * demuxer, int cmd, void * arg) { | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
281 nut_priv_tt * priv = demuxer->priv; |
19861 | 282 switch (cmd) { |
283 case DEMUXER_CTRL_GET_TIME_LENGTH: | |
284 *((double *)arg) = priv->s[0].max_pts * | |
21723 | 285 (double)priv->s[0].time_base.num / |
19861 | 286 priv->s[0].time_base.den; |
287 return DEMUXER_CTRL_OK; | |
288 case DEMUXER_CTRL_GET_PERCENT_POS: | |
21023
f5180197d7ad
fix demux_nut to give proper (estimate) of percent position after a seek
ods15
parents:
21022
diff
changeset
|
289 if (priv->s[0].max_pts == 0 || priv->last_pts == -1) |
19861 | 290 return DEMUXER_CTRL_DONTKNOW; |
291 *((int *)arg) = priv->last_pts * 100 / | |
292 (double)priv->s[0].max_pts; | |
293 return DEMUXER_CTRL_OK; | |
294 default: | |
295 return DEMUXER_CTRL_NOTIMPL; | |
296 } | |
297 } | |
298 | |
299 static void demux_close_nut(demuxer_t *demuxer) { | |
28099
3d88e7067d06
Rename typedefs in demux_nut to _tt instead of _t, sync to new libnut API
ods15
parents:
27730
diff
changeset
|
300 nut_priv_tt * priv = demuxer->priv; |
21011
b3fbda23e570
move demux_nut priv calloc to init() instead of check_file()
ods15
parents:
20971
diff
changeset
|
301 if (!priv) return; |
20925 | 302 nut_demuxer_uninit(priv->nut); |
19861 | 303 free(demuxer->priv); |
304 demuxer->priv = NULL; | |
305 } | |
306 | |
307 | |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
24118
diff
changeset
|
308 const demuxer_desc_t demuxer_desc_nut = { |
19861 | 309 "NUT demuxer", |
310 "nut", | |
311 "libnut", | |
312 "Oded Shimon (ods15)", | |
313 "NUT demuxer, requires libnut", | |
314 DEMUXER_TYPE_NUT, | |
315 1, // safe check demuxer | |
316 nut_check_file, | |
317 demux_nut_fill_buffer, | |
318 demux_open_nut, | |
319 demux_close_nut, | |
320 demux_seek_nut, | |
321 demux_control_nut | |
322 }; |