Mercurial > mplayer.hg
comparison libmpdemux/http.c @ 16013:4ee24ec6ac16
SHOUTcast and ultravox support
author | reimar |
---|---|
date | Tue, 19 Jul 2005 12:07:04 +0000 |
parents | 52edb32f0c2a |
children | c2e78215f0d9 |
comparison
equal
deleted
inserted
replaced
16012:f9e53883dfd2 | 16013:4ee24ec6ac16 |
---|---|
31 extern mime_struct_t mime_type_table[]; | 31 extern mime_struct_t mime_type_table[]; |
32 extern int stream_cache_size; | 32 extern int stream_cache_size; |
33 extern int network_bandwidth; | 33 extern int network_bandwidth; |
34 | 34 |
35 extern int http_seek(stream_t *stream, off_t pos); | 35 extern int http_seek(stream_t *stream, off_t pos); |
36 | |
37 typedef struct { | |
38 unsigned metaint; | |
39 unsigned metapos; | |
40 int is_ultravox; | |
41 } scast_data_t; | |
42 | |
43 /** | |
44 * \brief first read any data from sc->buffer then from fd | |
45 * \param fd file descriptor to read data from | |
46 * \param buffer buffer to read into | |
47 * \param len how many bytes to read | |
48 * \param sc streaming control containing buffer to read from first | |
49 * \return len unless there is a read error or eof | |
50 */ | |
51 static unsigned my_read(int fd, char *buffer, int len, streaming_ctrl_t *sc) { | |
52 unsigned pos = 0; | |
53 unsigned cp_len = sc->buffer_size - sc->buffer_pos; | |
54 if (cp_len > len) | |
55 cp_len = len; | |
56 memcpy(buffer, &sc->buffer[sc->buffer_pos], cp_len); | |
57 sc->buffer_pos += cp_len; | |
58 pos += cp_len; | |
59 while (pos < len) { | |
60 int ret = read(fd, &buffer[pos], len - pos); | |
61 if (ret <= 0) | |
62 break; | |
63 pos += ret; | |
64 } | |
65 return pos; | |
66 } | |
67 | |
68 static unsigned uvox_meta_read(int fd, streaming_ctrl_t *sc) { | |
69 unsigned metaint; | |
70 unsigned char info[6]; | |
71 do { | |
72 my_read(fd, info, 1, sc); | |
73 if (info[0] == 0x00) | |
74 my_read(fd, info, 6, sc); | |
75 else | |
76 my_read(fd, &info[1], 5, sc); | |
77 if (info[0] != 0x5a || info[1] != 0x00) { | |
78 mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid or unknown uvox metadata\n"); | |
79 return 0; | |
80 } | |
81 metaint = info[4] << 8 | info[5]; | |
82 if (info[3] == 0x02) { | |
83 char *metabuf = malloc(metaint); | |
84 my_read(fd, metabuf, metaint, sc); | |
85 free(metabuf); | |
86 } | |
87 } while (info[3] == 0x02); | |
88 return metaint; | |
89 } | |
90 | |
91 /** | |
92 * \brief read one scast meta data entry and print it | |
93 */ | |
94 static void scast_meta_read(int fd, streaming_ctrl_t *sc) { | |
95 unsigned char tmp = 0; | |
96 unsigned metalen; | |
97 my_read(fd, &tmp, 1, sc); | |
98 metalen = tmp * 16; | |
99 if (metalen > 0) { | |
100 char *info = (char *)malloc(metalen + 1); | |
101 unsigned nlen = my_read(fd, info, metalen, sc); | |
102 info[nlen] = 0; | |
103 mp_msg(MSGT_DEMUXER, MSGL_INFO, "\nICY Info: %s\n", info); | |
104 free(info); | |
105 } | |
106 } | |
107 | |
108 static int scast_streaming_read(int fd, char *buffer, int size, | |
109 streaming_ctrl_t *sc) { | |
110 scast_data_t *sd = (scast_data_t *)sc->data; | |
111 unsigned block, ret; | |
112 unsigned done = 0; | |
113 | |
114 // first read remaining data up to next metadata | |
115 block = sd->metaint - sd->metapos; | |
116 if (block > size) | |
117 block = size; | |
118 ret = my_read(fd, buffer, block, sc); | |
119 sd->metapos += ret; | |
120 done += ret; | |
121 if (ret != block) // read problems or eof | |
122 size = done; | |
123 | |
124 while (done < size) { // now comes the metadata | |
125 if (sd->is_ultravox) | |
126 sd->metaint = uvox_meta_read(fd, sc); | |
127 else | |
128 scast_meta_read(fd, sc); // read and display metadata | |
129 sd->metapos = 0; | |
130 block = size - done; | |
131 if (block > sd->metaint) | |
132 block = sd->metaint; | |
133 ret = my_read(fd, &buffer[done], block, sc); | |
134 sd->metapos += ret; | |
135 done += ret; | |
136 if (ret != block) // read problems or eof | |
137 size = done; | |
138 } | |
139 return done; | |
140 } | |
141 | |
142 static int scast_streaming_start(stream_t *stream) { | |
143 int metaint; | |
144 int fromhdr; | |
145 scast_data_t *scast_data; | |
146 HTTP_header_t *http_hdr = stream->streaming_ctrl->data; | |
147 int is_ultravox = http_hdr && strcasecmp(http_hdr->protocol, "ICY") != 0; | |
148 if (!stream || stream->fd < 0 || !http_hdr) | |
149 return -1; | |
150 if (is_ultravox) | |
151 metaint = 0; | |
152 else { | |
153 metaint = atoi(http_get_field(http_hdr, "Icy-MetaInt")); | |
154 if (metaint <= 0) | |
155 return -1; | |
156 } | |
157 stream->streaming_ctrl->buffer = malloc(http_hdr->body_size); | |
158 stream->streaming_ctrl->buffer_size = http_hdr->body_size; | |
159 stream->streaming_ctrl->buffer_pos = 0; | |
160 memcpy(stream->streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size); | |
161 scast_data = malloc(sizeof(scast_data_t)); | |
162 scast_data->metaint = metaint; | |
163 scast_data->metapos = 0; | |
164 scast_data->is_ultravox = is_ultravox; | |
165 http_free(http_hdr); | |
166 stream->streaming_ctrl->data = scast_data; | |
167 stream->streaming_ctrl->streaming_read = scast_streaming_read; | |
168 stream->streaming_ctrl->streaming_seek = NULL; | |
169 stream->streaming_ctrl->prebuffer_size = 64 * 1024; // 64 KBytes | |
170 stream->streaming_ctrl->buffering = 1; | |
171 stream->streaming_ctrl->status = streaming_playing_e; | |
172 return 0; | |
173 } | |
36 | 174 |
37 static int nop_streaming_start( stream_t *stream ) { | 175 static int nop_streaming_start( stream_t *stream ) { |
38 HTTP_header_t *http_hdr = NULL; | 176 HTTP_header_t *http_hdr = NULL; |
39 char *next_url=NULL; | 177 char *next_url=NULL; |
40 URL_t *rd_url=NULL; | 178 URL_t *rd_url=NULL; |
675 | 813 |
676 return -1; | 814 return -1; |
677 } | 815 } |
678 | 816 |
679 static int fixup_open(stream_t *stream,int seekable) { | 817 static int fixup_open(stream_t *stream,int seekable) { |
818 HTTP_header_t *http_hdr = stream->streaming_ctrl->data; | |
819 int is_icy = http_hdr && strcasecmp(http_hdr->protocol, "ICY") == 0; | |
820 char *content_type = http_get_field( http_hdr, "Content-Type" ); | |
821 int is_ultravox = http_hdr && content_type && | |
822 strcasecmp(content_type, "misc/ultravox") == 0; | |
680 | 823 |
681 stream->type = STREAMTYPE_STREAM; | 824 stream->type = STREAMTYPE_STREAM; |
682 if(seekable) | 825 if(!is_icy && !is_ultravox && seekable) |
683 { | 826 { |
684 stream->flags |= STREAM_SEEK; | 827 stream->flags |= STREAM_SEEK; |
685 stream->seek = http_seek; | 828 stream->seek = http_seek; |
686 } | 829 } |
687 stream->streaming_ctrl->bandwidth = network_bandwidth; | 830 stream->streaming_ctrl->bandwidth = network_bandwidth; |
831 if ((!is_icy && !is_ultravox) || scast_streaming_start(stream)) | |
688 if(nop_streaming_start( stream )) { | 832 if(nop_streaming_start( stream )) { |
689 mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_start failed\n"); | 833 mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_start failed\n"); |
690 streaming_ctrl_free(stream->streaming_ctrl); | 834 streaming_ctrl_free(stream->streaming_ctrl); |
691 stream->streaming_ctrl = NULL; | 835 stream->streaming_ctrl = NULL; |
692 return STREAM_UNSUPORTED; | 836 return STREAM_UNSUPORTED; |
749 "http streaming", | 893 "http streaming", |
750 "null", | 894 "null", |
751 "Bertrand, Albeau, Reimar Doeffinger, Arpi?", | 895 "Bertrand, Albeau, Reimar Doeffinger, Arpi?", |
752 "plain http", | 896 "plain http", |
753 open_s1, | 897 open_s1, |
754 {"http", "http_proxy", NULL}, | 898 {"http", "http_proxy", "unsv", NULL}, |
755 NULL, | 899 NULL, |
756 0 // Urls are an option string | 900 0 // Urls are an option string |
757 }; | 901 }; |
758 | 902 |
759 stream_info_t stream_info_http2 = { | 903 stream_info_t stream_info_http2 = { |