Mercurial > mplayer.hg
annotate libmpdemux/demux_nemesi.c @ 27319:09cf111f68b8
Revert to previous dependency checking behavior.
Take included header files into account when generating dependency files.
This has problems when header files are removed or renamed, but does not
silently miscompile files.
author | diego |
---|---|
date | Sat, 26 Jul 2008 18:36:48 +0000 |
parents | 7b85373802b7 |
children | 0f1b5b68af32 |
rev | line source |
---|---|
24564 | 1 /* |
26742
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
2 * Copyright (C) 2007 Alessandro Molina <amol.wrk@gmail.com> |
24564 | 3 * |
26742
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
4 * This file is part of MPlayer. |
24564 | 5 * |
26742
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
6 * MPlayer is free software; you can redistribute it and/or modify |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
7 * it under the terms of the GNU General Public License as published by |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
8 * the Free Software Foundation; either version 2 of the License, or |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
9 * (at your option) any later version. |
24564 | 10 * |
26742
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
11 * MPlayer is distributed in the hope that it will be useful, |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
14 * GNU General Public License for more details. |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
15 * |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
16 * You should have received a copy of the GNU General Public License along |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
0c1db5fd3f79
Use standard license headers with standard formatting.
diego
parents:
25965
diff
changeset
|
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
24564 | 19 */ |
25267 | 20 #include <stdlib.h> |
21 #include <stdio.h> | |
22 #include "stream/stream.h" | |
23 #include "demuxer.h" | |
24564 | 24 #include "stheader.h" |
25 #define HAVE_STRUCT_SOCKADDR_STORAGE | |
26 #include "nemesi/rtsp.h" | |
27 #include "nemesi/rtp.h" | |
24856 | 28 #include <sched.h> |
24564 | 29 |
30 int rtsp_transport_tcp = 0; | |
31 int rtsp_transport_sctp = 0; | |
25156 | 32 int rtsp_port = 0; |
24564 | 33 |
25103 | 34 typedef struct { |
35 char * mime; | |
36 unsigned int fourcc; | |
37 } MIMEto4CC; | |
38 | |
39 #define NMS_MAX_FORMATS 16 | |
40 | |
41 MIMEto4CC supported_audio[NMS_MAX_FORMATS] = { | |
42 {"MPA", 0x55}, | |
43 {"vorbis", mmioFOURCC('v','r','b','s')}, | |
25104 | 44 {"mpeg4-generic", mmioFOURCC('M','P','4','A')}, |
25103 | 45 {NULL, 0}, |
46 }; | |
47 | |
48 MIMEto4CC supported_video[NMS_MAX_FORMATS] = { | |
49 {"MPV", mmioFOURCC('M','P','E','G')}, | |
25116 | 50 {"theora",mmioFOURCC('t','h','e','o')}, |
25103 | 51 {"H264", mmioFOURCC('H','2','6','4')}, |
52 {"H263-1998", mmioFOURCC('H','2','6','3')}, | |
53 {"MP4V-ES", mmioFOURCC('M','P','4','V')}, | |
54 {NULL, 0}, | |
55 }; | |
56 | |
24564 | 57 typedef enum { NEMESI_SESSION_VIDEO, |
58 NEMESI_SESSION_AUDIO } Nemesi_SessionType; | |
59 | |
60 typedef struct { | |
61 rtsp_ctrl * rtsp; | |
62 rtp_session * session[2]; | |
63 rtp_frame first_pkt[2]; | |
64 double time[2]; | |
65 double seek; | |
66 } Nemesi_DemuxerStreamData; | |
67 | |
24997 | 68 |
69 #define STYPE_TO_DS(demuxer, stype) \ | |
70 ((stype) == NEMESI_SESSION_VIDEO ? (demuxer)->video : (demuxer)->audio) | |
71 | |
72 #define DS_TO_STYPE(demuxer, ds) \ | |
73 ((ds) == (demuxer)->video ? NEMESI_SESSION_VIDEO : NEMESI_SESSION_AUDIO) | |
74 | |
75 #define INVERT_STYPE(stype) ((stype + 1) % 2) | |
76 | |
25103 | 77 static unsigned int get4CC(MIMEto4CC * supported_formats, char const * format) |
78 { | |
79 unsigned i; | |
80 | |
81 for(i = 0; i < NMS_MAX_FORMATS; ++i) { | |
82 if (!supported_formats[i].mime) | |
83 return 0; | |
84 else if ( strcmp(supported_formats[i].mime, format) == 0 ) | |
85 return supported_formats[i].fourcc; | |
86 } | |
87 | |
88 return 0; | |
89 } | |
24997 | 90 |
91 static rtp_ssrc *wait_for_packets(Nemesi_DemuxerStreamData * ndsd, Nemesi_SessionType stype) | |
92 { | |
93 rtp_ssrc *ssrc = NULL; | |
94 | |
95 /* Wait for prebuffering (prebuffering must be enabled in nemesi) */ | |
96 int terminated = rtp_fill_buffers(rtsp_get_rtp_th(ndsd->rtsp)); | |
97 | |
98 /* Wait for the ssrc to be registered, if prebuffering is on in nemesi | |
99 this will just get immediatly the correct ssrc */ | |
100 if (!terminated) { | |
101 while ( !(ssrc = rtp_session_get_ssrc(ndsd->session[stype], ndsd->rtsp)) ) | |
102 sched_yield(); | |
103 } | |
104 | |
105 return ssrc; | |
106 } | |
107 | |
24564 | 108 static void link_session_and_fetch_conf(Nemesi_DemuxerStreamData * ndsd, |
109 Nemesi_SessionType stype, | |
110 rtp_session * sess, | |
111 rtp_buff * buff, unsigned int * fps) | |
112 { | |
25965 | 113 extern double force_fps; |
24855
2c790baff42c
Update to use newer libnemesi, should fix desync, fps guessing may fail now
lu_zero
parents:
24625
diff
changeset
|
114 rtp_ssrc *ssrc = NULL; |
24564 | 115 rtp_frame * fr = &ndsd->first_pkt[stype]; |
116 rtp_buff trash_buff; | |
25010 | 117 int must_prefetch = ((fps != NULL) || (buff != NULL)) ? 1 : 0; |
24564 | 118 |
119 ndsd->session[stype] = sess; | |
120 | |
24997 | 121 ssrc = wait_for_packets(ndsd, stype); |
24564 | 122 |
25010 | 123 if ( ((ssrc) && (must_prefetch)) ) { |
24997 | 124 if (buff == NULL) |
125 buff = &trash_buff; | |
24856 | 126 |
127 rtp_fill_buffer(ssrc, fr, buff); //Prefetch the first packet | |
24564 | 128 |
24998 | 129 /* Packet prefecthing must be done anyway or we won't be |
130 able to get the metadata, but fps calculation happens | |
131 only if the user didn't specify the FPS */ | |
25010 | 132 if ( ((!force_fps) && (fps != NULL)) ) { |
24998 | 133 while ( *fps <= 0 ) { |
134 //Wait more pkts to calculate FPS and try again | |
135 sched_yield(); | |
136 *fps = rtp_get_fps(ssrc); | |
137 } | |
138 } | |
24564 | 139 } |
140 } | |
141 | |
25267 | 142 static demuxer_t* demux_open_rtp(demuxer_t* demuxer) |
24564 | 143 { |
144 nms_rtsp_hints hints; | |
145 char * url = demuxer->stream->streaming_ctrl->url->url; | |
146 rtsp_ctrl * ctl; | |
147 RTSP_Error reply; | |
148 rtsp_medium * media; | |
149 Nemesi_DemuxerStreamData * ndsd = calloc(1, sizeof(Nemesi_DemuxerStreamData)); | |
150 | |
151 memset(&hints,0,sizeof(hints)); | |
25156 | 152 if (rtsp_port) hints.first_rtp_port = rtsp_port; |
24564 | 153 if (rtsp_transport_tcp) { |
154 hints.pref_rtsp_proto = TCP; | |
155 hints.pref_rtp_proto = TCP; | |
156 } | |
157 if (rtsp_transport_sctp) { | |
158 hints.pref_rtsp_proto = SCTP; | |
159 hints.pref_rtp_proto = SCTP; | |
160 } | |
161 | |
162 mp_msg(MSGT_DEMUX, MSGL_INFO, "Initializing libNemesi\n"); | |
163 if ((ctl = rtsp_init(&hints)) == NULL) { | |
164 free(ndsd); | |
165 return STREAM_ERROR; | |
166 } | |
167 | |
168 ndsd->rtsp = ctl; | |
169 demuxer->priv = ndsd; | |
170 //nms_verbosity_set(1); | |
171 | |
172 mp_msg(MSGT_DEMUX, MSGL_INFO, "Opening: %s\n", url); | |
173 if (rtsp_open(ctl, url)) { | |
174 mp_msg(MSGT_DEMUX, MSGL_ERR, "rtsp_open failed.\n"); | |
175 return demuxer; | |
176 } | |
177 | |
178 reply = rtsp_wait(ctl); | |
179 if (reply.got_error) { | |
180 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
181 "OPEN Error from the server: %s\n", | |
182 reply.message.reply_str); | |
183 return demuxer; | |
184 } | |
185 | |
186 rtsp_play(ctl, 0, 0); | |
187 reply = rtsp_wait(ctl); | |
188 if (reply.got_error) { | |
189 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
190 "PLAY Error from the server: %s\n", | |
191 reply.message.reply_str); | |
192 return demuxer; | |
193 } | |
194 | |
25490 | 195 if (!ctl->rtsp_queue) |
196 return demuxer; | |
197 | |
24564 | 198 media = ctl->rtsp_queue->media_queue; |
199 for (; media; media=media->next) { | |
200 sdp_medium_info * info = media->medium_info; | |
201 rtp_session * sess = media->rtp_sess; | |
25011 | 202 rtp_buff buff; |
24564 | 203 |
204 int media_format = atoi(info->fmts); | |
205 rtp_pt * ptinfo = rtp_get_pt_info(sess, media_format); | |
206 char const * format_name = ptinfo ? ptinfo->name : NULL; | |
207 | |
25011 | 208 memset(&buff, 0, sizeof(rtp_buff)); |
209 | |
24564 | 210 if (sess->parsers[media_format] == NULL) { |
211 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
212 "libNemesi unsupported media format: %s\n", | |
213 format_name ? format_name : info->fmts); | |
214 continue; | |
215 } | |
216 else { | |
217 mp_msg(MSGT_DEMUX, MSGL_INFO, | |
218 "libNemesi supported media: %s\n", | |
219 format_name); | |
220 } | |
221 | |
222 if (ptinfo->type == AU) { | |
223 if (ndsd->session[NEMESI_SESSION_AUDIO] == NULL) { | |
224 sh_audio_t* sh_audio = new_sh_audio(demuxer,0); | |
25011 | 225 WAVEFORMATEX* wf; |
24564 | 226 demux_stream_t* d_audio = demuxer->audio; |
27023 | 227 demuxer->audio->id = 0; |
24564 | 228 |
229 mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as AUDIO stream...\n"); | |
230 | |
231 link_session_and_fetch_conf(ndsd, NEMESI_SESSION_AUDIO, | |
25011 | 232 sess, &buff, NULL); |
233 | |
234 if (buff.len) { | |
235 wf = calloc(1,sizeof(WAVEFORMATEX)+buff.len); | |
236 wf->cbSize = buff.len; | |
237 memcpy(wf+1, buff.data, buff.len); | |
238 } else { | |
239 wf = calloc(1,sizeof(WAVEFORMATEX)); | |
240 } | |
24564 | 241 |
242 sh_audio->wf = wf; | |
243 d_audio->sh = sh_audio; | |
244 sh_audio->ds = d_audio; | |
245 wf->nSamplesPerSec = 0; | |
246 | |
25103 | 247 wf->wFormatTag = |
248 sh_audio->format = get4CC(supported_audio, format_name); | |
249 if ( !(wf->wFormatTag) ) | |
24564 | 250 mp_msg(MSGT_DEMUX, MSGL_WARN, |
251 "Unknown MPlayer format code for MIME" | |
252 " type \"audio/%s\"\n", format_name); | |
253 } else { | |
254 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
255 "There is already an audio session registered," | |
256 " ignoring...\n"); | |
257 } | |
258 } else if (ptinfo->type == VI) { | |
25012 | 259 if (ndsd->session[NEMESI_SESSION_VIDEO] == NULL) { |
24564 | 260 sh_video_t* sh_video; |
261 BITMAPINFOHEADER* bih; | |
262 demux_stream_t* d_video; | |
263 int fps = 0; | |
264 | |
265 mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as VIDEO stream...\n"); | |
266 | |
267 link_session_and_fetch_conf(ndsd, NEMESI_SESSION_VIDEO, | |
268 sess, &buff, &fps); | |
269 | |
270 if (buff.len) { | |
271 bih = calloc(1,sizeof(BITMAPINFOHEADER)+buff.len); | |
272 bih->biSize = sizeof(BITMAPINFOHEADER)+buff.len; | |
273 memcpy(bih+1, buff.data, buff.len); | |
274 } else { | |
275 bih = calloc(1,sizeof(BITMAPINFOHEADER)); | |
276 bih->biSize = sizeof(BITMAPINFOHEADER); | |
277 } | |
278 | |
279 sh_video = new_sh_video(demuxer,0); | |
280 sh_video->bih = bih; | |
281 d_video = demuxer->video; | |
282 d_video->sh = sh_video; | |
283 sh_video->ds = d_video; | |
284 | |
24856 | 285 if (fps) { |
24564 | 286 sh_video->fps = fps; |
24856 | 287 sh_video->frametime = 1.0/fps; |
288 } | |
24564 | 289 |
25103 | 290 bih->biCompression = |
291 sh_video->format = get4CC(supported_video, format_name); | |
292 if ( !(bih->biCompression) ) { | |
24564 | 293 mp_msg(MSGT_DEMUX, MSGL_WARN, |
294 "Unknown MPlayer format code for MIME" | |
295 " type \"video/%s\"\n", format_name); | |
296 } | |
297 } else { | |
298 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
299 "There is already a video session registered," | |
300 " ignoring...\n"); | |
301 } | |
302 } else { | |
303 mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported media type\n"); | |
304 } | |
305 } | |
306 | |
307 demuxer->stream->eof = 0; | |
308 | |
309 return demuxer; | |
310 } | |
311 | |
312 static int get_data_for_session(Nemesi_DemuxerStreamData * ndsd, | |
24997 | 313 Nemesi_SessionType stype, rtp_ssrc * ssrc, |
314 rtp_frame * fr) | |
24564 | 315 { |
24997 | 316 if (ndsd->first_pkt[stype].len != 0) { |
317 fr->data = ndsd->first_pkt[stype].data; | |
318 fr->time_sec = ndsd->first_pkt[stype].time_sec; | |
319 fr->len = ndsd->first_pkt[stype].len; | |
320 ndsd->first_pkt[stype].len = 0; | |
321 return RTP_FILL_OK; | |
322 } else { | |
323 rtp_buff buff; | |
324 return rtp_fill_buffer(ssrc, fr, &buff); | |
325 } | |
326 } | |
24564 | 327 |
24997 | 328 static void stream_add_packet(Nemesi_DemuxerStreamData * ndsd, |
329 Nemesi_SessionType stype, | |
330 demux_stream_t* ds, rtp_frame * fr) | |
331 { | |
332 demux_packet_t* dp = new_demux_packet(fr->len); | |
333 memcpy(dp->buffer, fr->data, fr->len); | |
24564 | 334 |
24997 | 335 fr->time_sec += ndsd->seek; |
336 ndsd->time[stype] = dp->pts = fr->time_sec; | |
337 | |
338 ds_add_packet(ds, dp); | |
24564 | 339 } |
340 | |
25267 | 341 static int demux_rtp_fill_buffer(demuxer_t* demuxer, demux_stream_t* ds) |
24564 | 342 { |
343 Nemesi_DemuxerStreamData * ndsd = demuxer->priv; | |
344 Nemesi_SessionType stype; | |
24997 | 345 rtp_ssrc * ssrc; |
24564 | 346 rtp_frame fr; |
347 | |
24997 | 348 if ( (!ndsd->rtsp->rtsp_queue) || (demuxer->stream->eof) ) { |
24564 | 349 mp_msg(MSGT_DEMUX, MSGL_INFO, "End of Stream...\n"); |
350 demuxer->stream->eof = 1; | |
351 return 0; | |
352 } | |
353 | |
25103 | 354 memset(&fr, 0, sizeof(fr)); |
355 | |
24997 | 356 stype = DS_TO_STYPE(demuxer, ds); |
357 if ( (ssrc = wait_for_packets(ndsd, stype)) == NULL ) { | |
358 mp_msg(MSGT_DEMUX, MSGL_INFO, "Bye...\n"); | |
359 demuxer->stream->eof = 1; | |
24564 | 360 return 0; |
361 } | |
362 | |
24997 | 363 if(!get_data_for_session(ndsd, stype, ssrc, &fr)) |
364 stream_add_packet(ndsd, stype, ds, &fr); | |
365 else { | |
366 stype = INVERT_STYPE(stype); | |
25013
dc6b7ad240db
Check for second stream presence, fixes single stream playback (from amol)
lu_zero
parents:
25012
diff
changeset
|
367 |
dc6b7ad240db
Check for second stream presence, fixes single stream playback (from amol)
lu_zero
parents:
25012
diff
changeset
|
368 //Must check if we actually have a stream of the other type |
dc6b7ad240db
Check for second stream presence, fixes single stream playback (from amol)
lu_zero
parents:
25012
diff
changeset
|
369 if (!ndsd->session[stype]) |
dc6b7ad240db
Check for second stream presence, fixes single stream playback (from amol)
lu_zero
parents:
25012
diff
changeset
|
370 return 1; |
dc6b7ad240db
Check for second stream presence, fixes single stream playback (from amol)
lu_zero
parents:
25012
diff
changeset
|
371 |
24997 | 372 ds = STYPE_TO_DS(demuxer, stype); |
373 ssrc = wait_for_packets(ndsd, stype); | |
374 | |
375 if(!get_data_for_session(ndsd, stype, ssrc, &fr)) | |
376 stream_add_packet(ndsd, stype, ds, &fr); | |
24564 | 377 } |
378 | |
379 return 1; | |
380 } | |
381 | |
382 | |
25267 | 383 static void demux_close_rtp(demuxer_t* demuxer) |
24564 | 384 { |
385 Nemesi_DemuxerStreamData * ndsd = demuxer->priv; | |
386 rtsp_ctrl * ctl = ndsd->rtsp; | |
387 RTSP_Error err; | |
388 | |
389 mp_msg(MSGT_DEMUX, MSGL_INFO, "Closing libNemesi RTSP Stream...\n"); | |
390 | |
391 if (ndsd == NULL) | |
392 return; | |
393 | |
394 free(ndsd); | |
395 | |
396 if (rtsp_close(ctl)) { | |
397 err = rtsp_wait(ctl); | |
398 if (err.got_error) | |
399 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
400 "Error Closing Stream: %s\n", | |
401 err.message.reply_str); | |
402 } | |
403 | |
404 rtsp_uninit(ctl); | |
405 } | |
406 | |
407 static void demux_seek_rtp(demuxer_t *demuxer, float rel_seek_secs, | |
408 float audio_delay, int flags) | |
409 { | |
410 Nemesi_DemuxerStreamData * ndsd = demuxer->priv; | |
411 rtsp_ctrl * ctl = ndsd->rtsp; | |
412 sdp_attr * r_attr = NULL; | |
413 sdp_range r = {0, 0}; | |
414 double time = ndsd->time[NEMESI_SESSION_VIDEO] ? | |
415 ndsd->time[NEMESI_SESSION_VIDEO] : | |
416 ndsd->time[NEMESI_SESSION_AUDIO]; | |
417 | |
418 if (!ctl->rtsp_queue) | |
419 return; | |
420 | |
421 r_attr = sdp_get_attr(ctl->rtsp_queue->info->attr_list, "range"); | |
422 if (r_attr) | |
423 r = sdp_parse_range(r_attr->value); | |
424 | |
425 //flags & 1 -> absolute seek | |
426 //flags & 2 -> percent seek | |
427 if (flags == 0) { | |
428 time += rel_seek_secs; | |
429 if (time < r.begin) | |
430 time = r.begin; | |
431 else if (time > r.end) | |
432 time = r.end; | |
433 ndsd->seek = time; | |
434 | |
435 mp_msg(MSGT_DEMUX,MSGL_WARN,"libNemesi SEEK %f on %f - %f)\n", | |
436 time, r.begin, r.end); | |
437 | |
438 if (!rtsp_seek(ctl, time, 0)) { | |
439 RTSP_Error err = rtsp_wait(ctl); | |
440 if (err.got_error) { | |
441 mp_msg(MSGT_DEMUX, MSGL_ERR, | |
442 "Error Performing Seek: %s\n", | |
443 err.message.reply_str); | |
444 demuxer->stream->eof = 1; | |
445 } | |
446 else | |
447 mp_msg(MSGT_DEMUX, MSGL_INFO, "Seek, performed\n"); | |
448 } | |
449 else { | |
450 mp_msg(MSGT_DEMUX, MSGL_ERR, "Unable to pause stream to perform seek\n"); | |
451 demuxer->stream->eof = 1; | |
452 } | |
453 } | |
454 else | |
455 mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported seek type\n"); | |
456 } | |
457 | |
458 static int demux_rtp_control(struct demuxer_st *demuxer, int cmd, void *arg) | |
459 { | |
460 Nemesi_DemuxerStreamData * ndsd = demuxer->priv; | |
461 rtsp_ctrl * ctl = ndsd->rtsp; | |
462 sdp_attr * r_attr = NULL; | |
463 sdp_range r = {0, 0}; | |
464 double time = ndsd->time[NEMESI_SESSION_VIDEO] ? | |
465 ndsd->time[NEMESI_SESSION_VIDEO] : | |
466 ndsd->time[NEMESI_SESSION_AUDIO]; | |
467 | |
468 if (!ctl->rtsp_queue) | |
469 return DEMUXER_CTRL_DONTKNOW; | |
470 | |
471 r_attr = sdp_get_attr(ctl->rtsp_queue->info->attr_list, "range"); | |
472 if (r_attr) | |
473 r = sdp_parse_range(r_attr->value); | |
474 | |
475 switch (cmd) { | |
476 case DEMUXER_CTRL_GET_TIME_LENGTH: | |
477 if (r.end == 0) | |
478 return DEMUXER_CTRL_DONTKNOW; | |
479 | |
480 *((double *)arg) = ((double)r.end) - ((double)r.begin); | |
481 return DEMUXER_CTRL_OK; | |
482 | |
483 case DEMUXER_CTRL_GET_PERCENT_POS: | |
484 if (r.end == 0) | |
485 return DEMUXER_CTRL_DONTKNOW; | |
486 | |
487 *((int *)arg) = (int)( time * 100 / (r.end - r.begin) ); | |
488 return DEMUXER_CTRL_OK; | |
489 default: | |
490 return DEMUXER_CTRL_DONTKNOW; | |
491 } | |
492 } | |
493 | |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
25490
diff
changeset
|
494 const demuxer_desc_t demuxer_desc_rtp_nemesi = { |
25270 | 495 "libnemesi RTP demuxer", |
496 "nemesi", | |
24564 | 497 "", |
498 "Alessandro Molina", | |
25270 | 499 "requires libnemesi", |
25266
239330301b33
Make libnemesi use specific struct and DEMUXER_TYPE
lu_zero
parents:
25156
diff
changeset
|
500 DEMUXER_TYPE_RTP_NEMESI, |
24564 | 501 0, // no autodetect |
502 NULL, | |
503 demux_rtp_fill_buffer, | |
504 demux_open_rtp, | |
505 demux_close_rtp, | |
506 demux_seek_rtp, | |
507 demux_rtp_control | |
508 }; |