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