Mercurial > mplayer.hg
annotate libmpdemux/demux_nut.c @ 25284:e60a367eb80e
suppress silly messages when checktree is not called from the root of the tree
but nevertheless has no specific arguments to work with. it will traverse
the tree from there, but obviously cannot find our externals.
author | ivo |
---|---|
date | Wed, 05 Dec 2007 23:44:31 +0000 |
parents | f135a7260fd0 |
children | d4fe6e23283e |
rev | line source |
---|---|
19861 | 1 #include <stdio.h> |
20815 | 2 #include <stdlib.h> |
19861 | 3 |
4 #include "config.h" | |
5 #include "mp_msg.h" | |
6 | |
23084 | 7 #include "help_mp.h" |
8 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
22484
diff
changeset
|
9 #include "stream/stream.h" |
19861 | 10 #include "demuxer.h" |
11 #include "stheader.h" | |
12 | |
20893 | 13 #include <libnut.h> |
19861 | 14 |
15 typedef struct { | |
16 int last_pts; // FIXME | |
17 nut_context_t * nut; | |
18 nut_stream_header_t * s; | |
19 } nut_priv_t; | |
20 | |
21 static size_t mp_read(void * h, size_t len, uint8_t * buf) { | |
22 stream_t * stream = (stream_t*)h; | |
23 | |
24 if(stream_eof(stream)) return 0; | |
21022 | 25 //len = MIN(len, 5); |
19861 | 26 |
27 return stream_read(stream, buf, len); | |
28 } | |
29 | |
21022 | 30 static int mp_eof(void * h) { |
31 stream_t * stream = (stream_t*)h; | |
32 if(stream_eof(stream)) return 1; | |
33 return 0; | |
34 } | |
35 | |
19861 | 36 static off_t mp_seek(void * h, long long pos, int whence) { |
37 stream_t * stream = (stream_t*)h; | |
38 | |
39 if (stream->end_pos < stream_tell(stream)) | |
40 stream->end_pos = stream_tell(stream); | |
41 | |
42 if (whence == SEEK_CUR) pos += stream_tell(stream); | |
43 else if (whence == SEEK_END) pos += stream->end_pos; | |
44 else if (whence != SEEK_SET) return -1; | |
45 | |
46 if (pos < stream->end_pos && stream->eof) stream_reset(stream); | |
47 if (stream_seek(stream, pos) == 0) return -1; | |
48 | |
49 return pos; | |
50 } | |
51 | |
52 #define ID_STRING "nut/multimedia container" | |
53 #define ID_LENGTH (strlen(ID_STRING) + 1) | |
54 | |
55 static int nut_check_file(demuxer_t * demuxer) { | |
56 uint8_t buf[ID_LENGTH]; | |
57 | |
58 if (stream_read(demuxer->stream, buf, ID_LENGTH) != ID_LENGTH) return 0; | |
59 | |
60 if (memcmp(buf, ID_STRING, ID_LENGTH)) return 0; | |
61 | |
62 stream_seek(demuxer->stream, 0); | |
63 return DEMUXER_TYPE_NUT; | |
64 } | |
65 | |
66 static demuxer_t * demux_open_nut(demuxer_t * demuxer) { | |
67 extern int index_mode; | |
68 nut_demuxer_opts_t dopts = { | |
69 .input = { | |
70 .priv = demuxer->stream, | |
71 .seek = mp_seek, | |
72 .read = mp_read, | |
21022 | 73 .eof = mp_eof, |
19861 | 74 .file_pos = stream_tell(demuxer->stream), |
75 }, | |
19957 | 76 .alloc = { .malloc = NULL }, |
20909 | 77 .read_index = index_mode, |
78 .cache_syncpoints = 1, | |
19861 | 79 }; |
21011
b3fbda23e570
move demux_nut priv calloc to init() instead of check_file()
ods15
parents:
20971
diff
changeset
|
80 nut_priv_t * priv = demuxer->priv = calloc(1, sizeof(nut_priv_t)); |
19861 | 81 nut_context_t * nut = priv->nut = nut_demuxer_init(&dopts); |
82 nut_stream_header_t * s; | |
83 int ret; | |
84 int i; | |
85 | |
21022 | 86 while ((ret = nut_read_headers(nut, &s, NULL)) == NUT_ERR_EAGAIN); |
87 if (ret) { | |
20938 | 88 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret)); |
19861 | 89 nut_demuxer_uninit(nut); |
90 free(priv); | |
91 return NULL; | |
92 } | |
93 | |
94 priv->s = s; | |
95 | |
96 for (i = 0; s[i].type != -1 && i < 2; i++) switch(s[i].type) { | |
97 case NUT_AUDIO_CLASS: { | |
98 WAVEFORMATEX *wf = | |
99 calloc(sizeof(WAVEFORMATEX) + | |
100 s[i].codec_specific_len, 1); | |
101 sh_audio_t* sh_audio = new_sh_audio(demuxer, i); | |
23010
74efb0fa8a0b
with -identify show audio and video id; patch by Andrew Savchenko (Bircoph list ru)
nicodvb
parents:
22605
diff
changeset
|
102 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "nut", i); |
19861 | 103 int j; |
104 | |
105 sh_audio->wf= wf; sh_audio->ds = demuxer->audio; | |
106 sh_audio->audio.dwSampleSize = 0; // FIXME | |
21723 | 107 sh_audio->audio.dwScale = s[i].time_base.num; |
19861 | 108 sh_audio->audio.dwRate = s[i].time_base.den; |
109 sh_audio->format = 0; | |
110 for (j = 0; j < s[i].fourcc_len && j < 4; j++) | |
111 sh_audio->format |= s[i].fourcc[j]<<(j*8); | |
112 sh_audio->channels = s[i].channel_count; | |
113 sh_audio->samplerate = | |
21723 | 114 s[i].samplerate_num / s[i].samplerate_denom; |
19861 | 115 sh_audio->i_bps = 0; // FIXME |
116 | |
117 wf->wFormatTag = sh_audio->format; | |
118 wf->nChannels = s[i].channel_count; | |
119 wf->nSamplesPerSec = | |
21723 | 120 s[i].samplerate_num / s[i].samplerate_denom; |
19861 | 121 wf->nAvgBytesPerSec = 0; // FIXME |
122 wf->nBlockAlign = 0; // FIXME | |
123 wf->wBitsPerSample = 0; // FIXME | |
124 wf->cbSize = s[i].codec_specific_len; | |
125 if (s[i].codec_specific_len) | |
126 memcpy(wf + 1, s[i].codec_specific, | |
127 s[i].codec_specific_len); | |
128 | |
129 demuxer->audio->id = i; | |
130 demuxer->audio->sh= demuxer->a_streams[i]; | |
131 break; | |
132 } | |
133 case NUT_VIDEO_CLASS: { | |
134 BITMAPINFOHEADER * bih = | |
135 calloc(sizeof(BITMAPINFOHEADER) + | |
136 s[i].codec_specific_len, 1); | |
137 sh_video_t * sh_video = new_sh_video(demuxer, i); | |
23010
74efb0fa8a0b
with -identify show audio and video id; patch by Andrew Savchenko (Bircoph list ru)
nicodvb
parents:
22605
diff
changeset
|
138 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "nut", i); |
19861 | 139 int j; |
140 | |
141 sh_video->bih = bih; | |
142 sh_video->ds = demuxer->video; | |
143 sh_video->disp_w = s[i].width; | |
144 sh_video->disp_h = s[i].height; | |
21723 | 145 sh_video->video.dwScale = s[i].time_base.num; |
19861 | 146 sh_video->video.dwRate = s[i].time_base.den; |
147 | |
148 sh_video->fps = sh_video->video.dwRate/ | |
149 (float)sh_video->video.dwScale; | |
150 sh_video->frametime = 1./sh_video->fps; | |
151 sh_video->format = 0; | |
152 for (j = 0; j < s[i].fourcc_len && j < 4; j++) | |
153 sh_video->format |= s[i].fourcc[j]<<(j*8); | |
154 if (!s[i].sample_height) sh_video->aspect = 0; | |
155 else sh_video->aspect = | |
156 s[i].sample_width / (float)s[i].sample_height; | |
157 sh_video->i_bps = 0; // FIXME | |
158 | |
159 bih->biSize = sizeof(BITMAPINFOHEADER) + | |
160 s[i].codec_specific_len; | |
161 bih->biWidth = s[i].width; | |
162 bih->biHeight = s[i].height; | |
163 bih->biBitCount = 0; // FIXME | |
164 bih->biSizeImage = 0; // FIXME | |
165 bih->biCompression = sh_video->format; | |
166 | |
167 if (s[i].codec_specific_len) | |
168 memcpy(bih + 1, s[i].codec_specific, | |
169 s[i].codec_specific_len); | |
170 | |
171 demuxer->video->id = i; | |
172 demuxer->video->sh = demuxer->v_streams[i]; | |
173 break; | |
174 } | |
175 } | |
176 | |
177 return demuxer; | |
178 } | |
179 | |
180 static int demux_nut_fill_buffer(demuxer_t * demuxer, demux_stream_t * dsds) { | |
181 nut_priv_t * priv = demuxer->priv; | |
182 nut_context_t * nut = priv->nut; | |
183 demux_packet_t *dp; | |
184 demux_stream_t *ds; | |
185 nut_packet_t pd; | |
186 int ret; | |
187 double pts; | |
188 | |
189 demuxer->filepos = stream_tell(demuxer->stream); | |
190 if (stream_eof(demuxer->stream)) return 0; | |
191 | |
21022 | 192 while ((ret = nut_read_next_packet(nut, &pd)) == NUT_ERR_EAGAIN); |
20938 | 193 if (ret) { |
194 if (ret != NUT_ERR_EOF) | |
195 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", | |
196 nut_error(ret)); | |
197 return 0; // fatal error | |
19861 | 198 } |
199 | |
21723 | 200 pts = (double)pd.pts * priv->s[pd.stream].time_base.num / |
19861 | 201 priv->s[pd.stream].time_base.den; |
202 | |
203 if (pd.stream == demuxer->audio->id) { | |
204 ds = demuxer->audio; | |
205 } | |
206 else if (pd.stream == demuxer->video->id) { | |
207 ds = demuxer->video; | |
208 } | |
209 else { | |
20926 | 210 uint8_t buf[pd.len]; |
21022 | 211 while ((ret = nut_read_frame(nut, &pd.len, buf)) == NUT_ERR_EAGAIN); |
20938 | 212 if (ret) { |
19958 | 213 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", |
20938 | 214 nut_error(ret)); |
215 return 0; // fatal error | |
19861 | 216 } |
217 return 1; | |
218 } | |
219 | |
220 if (pd.stream == 0) priv->last_pts = pd.pts; | |
221 | |
222 dp = new_demux_packet(pd.len); | |
223 | |
224 dp->pts = pts; | |
225 | |
226 dp->pos = demuxer->filepos; | |
227 dp->flags= (pd.flags & NUT_FLAG_KEY) ? 0x10 : 0; | |
228 | |
21022 | 229 {int len = pd.len; |
230 while ((ret = nut_read_frame(nut, &len, dp->buffer + pd.len-len)) == NUT_ERR_EAGAIN); | |
231 } | |
20938 | 232 if (ret) { |
19958 | 233 mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", |
20938 | 234 nut_error(ret)); |
235 return 0; // fatal error | |
19861 | 236 } |
19958 | 237 |
19861 | 238 ds_add_packet(ds, dp); // append packet to DS stream |
239 return 1; | |
240 } | |
241 | |
242 static void demux_seek_nut(demuxer_t * demuxer, float time_pos, float audio_delay, int flags) { | |
243 nut_context_t * nut = ((nut_priv_t*)demuxer->priv)->nut; | |
244 nut_priv_t * priv = demuxer->priv; | |
245 sh_audio_t * sh_audio = demuxer->audio->sh; | |
246 int nutflags = 0; | |
247 int ret; | |
248 const int tmp[] = { 0, -1 }; | |
249 | |
250 if (!(flags & 1)) { | |
251 nutflags |= 1; // relative | |
252 if (time_pos > 0) nutflags |= 2; // forwards | |
253 } | |
254 | |
255 if (flags & 2) // percent | |
256 time_pos *= priv->s[0].max_pts * | |
21723 | 257 (double)priv->s[0].time_base.num / |
19861 | 258 priv->s[0].time_base.den; |
259 | |
21022 | 260 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
|
261 priv->last_pts = -1; |
20971
e243a3de18c2
missed piece in update to libnut API - non negative errors
ods15
parents:
20938
diff
changeset
|
262 if (ret) mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret)); |
19861 | 263 if (sh_audio) resync_audio_stream(sh_audio); |
21023
f5180197d7ad
fix demux_nut to give proper (estimate) of percent position after a seek
ods15
parents:
21022
diff
changeset
|
264 demuxer->filepos = stream_tell(demuxer->stream); |
19861 | 265 } |
266 | |
267 static int demux_control_nut(demuxer_t * demuxer, int cmd, void * arg) { | |
268 nut_priv_t * priv = demuxer->priv; | |
269 switch (cmd) { | |
270 case DEMUXER_CTRL_GET_TIME_LENGTH: | |
271 *((double *)arg) = priv->s[0].max_pts * | |
21723 | 272 (double)priv->s[0].time_base.num / |
19861 | 273 priv->s[0].time_base.den; |
274 return DEMUXER_CTRL_OK; | |
275 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
|
276 if (priv->s[0].max_pts == 0 || priv->last_pts == -1) |
19861 | 277 return DEMUXER_CTRL_DONTKNOW; |
278 *((int *)arg) = priv->last_pts * 100 / | |
279 (double)priv->s[0].max_pts; | |
280 return DEMUXER_CTRL_OK; | |
281 default: | |
282 return DEMUXER_CTRL_NOTIMPL; | |
283 } | |
284 } | |
285 | |
286 static void demux_close_nut(demuxer_t *demuxer) { | |
20925 | 287 nut_priv_t * priv = demuxer->priv; |
21011
b3fbda23e570
move demux_nut priv calloc to init() instead of check_file()
ods15
parents:
20971
diff
changeset
|
288 if (!priv) return; |
20925 | 289 nut_demuxer_uninit(priv->nut); |
19861 | 290 free(demuxer->priv); |
291 demuxer->priv = NULL; | |
292 } | |
293 | |
294 | |
295 demuxer_desc_t demuxer_desc_nut = { | |
296 "NUT demuxer", | |
297 "nut", | |
298 "libnut", | |
299 "Oded Shimon (ods15)", | |
300 "NUT demuxer, requires libnut", | |
301 DEMUXER_TYPE_NUT, | |
302 1, // safe check demuxer | |
303 nut_check_file, | |
304 demux_nut_fill_buffer, | |
305 demux_open_nut, | |
306 demux_close_nut, | |
307 demux_seek_nut, | |
308 demux_control_nut | |
309 }; |