Patch by Howard Chu <hyc * highlandsun * com>.
Originally committed as revision 22710 to svn://svn.ffmpeg.org/ffmpeg/trunk
... | ... |
@@ -177,6 +177,7 @@ External library support: |
177 | 177 |
--enable-libnut enable NUT (de)muxing via libnut, |
178 | 178 |
native (de)muxer exists [no] |
179 | 179 |
--enable-libopenjpeg enable JPEG 2000 decoding via OpenJPEG [no] |
180 |
+ --enable-librtmp enable RTMP[E] support via librtmp [no] |
|
180 | 181 |
--enable-libschroedinger enable Dirac support via libschroedinger [no] |
181 | 182 |
--enable-libspeex enable Speex decoding via libspeex [no] |
182 | 183 |
--enable-libtheora enable Theora encoding via libtheora [no] |
... | ... |
@@ -920,6 +921,7 @@ CONFIG_LIST=" |
920 | 920 |
libopencore_amrnb |
921 | 921 |
libopencore_amrwb |
922 | 922 |
libopenjpeg |
923 |
+ librtmp |
|
923 | 924 |
libschroedinger |
924 | 925 |
libspeex |
925 | 926 |
libtheora |
... | ... |
@@ -2615,6 +2617,7 @@ enabled libnut && require libnut libnut.h nut_demuxer_init -lnut |
2615 | 2615 |
enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb -lm |
2616 | 2616 |
enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb -lm |
2617 | 2617 |
enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg |
2618 |
+enabled librtmp && require librtmp librtmp/rtmp.h RTMP_Init -lrtmp |
|
2618 | 2619 |
enabled libschroedinger && add_cflags $(pkg-config --cflags schroedinger-1.0) && |
2619 | 2620 |
require libschroedinger schroedinger/schro.h schro_init $(pkg-config --libs schroedinger-1.0) |
2620 | 2621 |
enabled libspeex && require libspeex speex/speex.h speex_decoder_init -lspeex |
... | ... |
@@ -2893,6 +2896,7 @@ echo "libnut enabled ${libnut-no}" |
2893 | 2893 |
echo "libopencore-amrnb support ${libopencore_amrnb-no}" |
2894 | 2894 |
echo "libopencore-amrwb support ${libopencore_amrwb-no}" |
2895 | 2895 |
echo "libopenjpeg enabled ${libopenjpeg-no}" |
2896 |
+echo "librtmp enabled ${librtmp-no}" |
|
2896 | 2897 |
echo "libschroedinger enabled ${libschroedinger-no}" |
2897 | 2898 |
echo "libspeex enabled ${libspeex-no}" |
2898 | 2899 |
echo "libtheora enabled ${libtheora-no}" |
... | ... |
@@ -274,7 +274,12 @@ OBJS-$(CONFIG_FILE_PROTOCOL) += file.o |
274 | 274 |
OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o |
275 | 275 |
OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o |
276 | 276 |
OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o |
277 |
-OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o |
|
277 |
+ |
|
278 |
+# external or internal rtmp |
|
279 |
+RTMP-OBJS-$(CONFIG_LIBRTMP) = librtmp.o |
|
280 |
+RTMP-OBJS-$(!CONFIG_LIBRTMP) = rtmpproto.o rtmppkt.o |
|
281 |
+OBJS-$(CONFIG_RTMP_PROTOCOL) += $(RTMP-OBJS-yes) |
|
282 |
+ |
|
278 | 283 |
OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o |
279 | 284 |
OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o |
280 | 285 |
OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o |
... | ... |
@@ -218,6 +218,12 @@ void av_register_all(void) |
218 | 218 |
REGISTER_PROTOCOL (HTTP, http); |
219 | 219 |
REGISTER_PROTOCOL (PIPE, pipe); |
220 | 220 |
REGISTER_PROTOCOL (RTMP, rtmp); |
221 |
+#if CONFIG_LIBRTMP |
|
222 |
+ REGISTER_PROTOCOL (RTMP, rtmpt); |
|
223 |
+ REGISTER_PROTOCOL (RTMP, rtmpe); |
|
224 |
+ REGISTER_PROTOCOL (RTMP, rtmpte); |
|
225 |
+ REGISTER_PROTOCOL (RTMP, rtmps); |
|
226 |
+#endif |
|
221 | 227 |
REGISTER_PROTOCOL (RTP, rtp); |
222 | 228 |
REGISTER_PROTOCOL (TCP, tcp); |
223 | 229 |
REGISTER_PROTOCOL (UDP, udp); |
... | ... |
@@ -22,8 +22,8 @@ |
22 | 22 |
#define AVFORMAT_AVFORMAT_H |
23 | 23 |
|
24 | 24 |
#define LIBAVFORMAT_VERSION_MAJOR 52 |
25 |
-#define LIBAVFORMAT_VERSION_MINOR 57 |
|
26 |
-#define LIBAVFORMAT_VERSION_MICRO 1 |
|
25 |
+#define LIBAVFORMAT_VERSION_MINOR 58 |
|
26 |
+#define LIBAVFORMAT_VERSION_MICRO 0 |
|
27 | 27 |
|
28 | 28 |
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |
29 | 29 |
LIBAVFORMAT_VERSION_MINOR, \ |
30 | 30 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,206 @@ |
0 |
+/* |
|
1 |
+ * RTMP network protocol |
|
2 |
+ * Copyright (c) 2010 Howard Chu |
|
3 |
+ * |
|
4 |
+ * This file is part of FFmpeg. |
|
5 |
+ * |
|
6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
8 |
+ * License as published by the Free Software Foundation; either |
|
9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
10 |
+ * |
|
11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 |
+ * Lesser General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+/** |
|
22 |
+ * @file libavformat/librtmp.c |
|
23 |
+ * RTMP protocol based on http://rtmpdump.mplayerhq.hu librtmp |
|
24 |
+ */ |
|
25 |
+ |
|
26 |
+#include "avformat.h" |
|
27 |
+ |
|
28 |
+#include <librtmp/rtmp.h> |
|
29 |
+#include <librtmp/log.h> |
|
30 |
+ |
|
31 |
+static int rtmp_close(URLContext *s) |
|
32 |
+{ |
|
33 |
+ RTMP *r = s->priv_data; |
|
34 |
+ |
|
35 |
+ RTMP_Close(r); |
|
36 |
+ av_free(r); |
|
37 |
+ return 0; |
|
38 |
+} |
|
39 |
+ |
|
40 |
+/** |
|
41 |
+ * Opens RTMP connection and verifies that the stream can be played. |
|
42 |
+ * |
|
43 |
+ * URL syntax: rtmp://server[:port][/app][/playpath][ keyword=value]... |
|
44 |
+ * where 'app' is first one or two directories in the path |
|
45 |
+ * (e.g. /ondemand/, /flash/live/, etc.) |
|
46 |
+ * and 'playpath' is a file name (the rest of the path, |
|
47 |
+ * may be prefixed with "mp4:") |
|
48 |
+ * |
|
49 |
+ * Additional RTMP library options may be appended as |
|
50 |
+ * space-separated key-value pairs. |
|
51 |
+ */ |
|
52 |
+static int rtmp_open(URLContext *s, const char *uri, int flags) |
|
53 |
+{ |
|
54 |
+ RTMP *r; |
|
55 |
+ int rc; |
|
56 |
+ |
|
57 |
+ r = av_mallocz(sizeof(RTMP)); |
|
58 |
+ if (!r) |
|
59 |
+ return AVERROR(ENOMEM); |
|
60 |
+ |
|
61 |
+ switch(av_log_get_level()) { |
|
62 |
+ default: |
|
63 |
+ case AV_LOG_FATAL: rc = RTMP_LOGCRIT; break; |
|
64 |
+ case AV_LOG_ERROR: rc = RTMP_LOGERROR; break; |
|
65 |
+ case AV_LOG_WARNING: rc = RTMP_LOGWARNING; break; |
|
66 |
+ case AV_LOG_INFO: rc = RTMP_LOGINFO; break; |
|
67 |
+ case AV_LOG_VERBOSE: rc = RTMP_LOGDEBUG; break; |
|
68 |
+ case AV_LOG_DEBUG: rc = RTMP_LOGDEBUG2; break; |
|
69 |
+ } |
|
70 |
+ RTMP_LogSetLevel(rc); |
|
71 |
+ |
|
72 |
+ RTMP_Init(r); |
|
73 |
+ if (!RTMP_SetupURL(r, s->filename)) { |
|
74 |
+ rc = -1; |
|
75 |
+ goto fail; |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ if (flags & URL_WRONLY) |
|
79 |
+ r->Link.protocol |= RTMP_FEATURE_WRITE; |
|
80 |
+ |
|
81 |
+ if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) { |
|
82 |
+ rc = -1; |
|
83 |
+ goto fail; |
|
84 |
+ } |
|
85 |
+ |
|
86 |
+ s->priv_data = r; |
|
87 |
+ s->is_streamed = 1; |
|
88 |
+ return 0; |
|
89 |
+fail: |
|
90 |
+ av_free(r); |
|
91 |
+ return rc; |
|
92 |
+} |
|
93 |
+ |
|
94 |
+static int rtmp_write(URLContext *s, uint8_t *buf, int size) |
|
95 |
+{ |
|
96 |
+ RTMP *r = s->priv_data; |
|
97 |
+ |
|
98 |
+ return RTMP_Write(r, buf, size); |
|
99 |
+} |
|
100 |
+ |
|
101 |
+static int rtmp_read(URLContext *s, uint8_t *buf, int size) |
|
102 |
+{ |
|
103 |
+ RTMP *r = s->priv_data; |
|
104 |
+ |
|
105 |
+ return RTMP_Read(r, buf, size); |
|
106 |
+} |
|
107 |
+ |
|
108 |
+static int rtmp_read_pause(URLContext *s, int pause) |
|
109 |
+{ |
|
110 |
+ RTMP *r = s->priv_data; |
|
111 |
+ |
|
112 |
+ if (pause) |
|
113 |
+ r->m_pauseStamp = |
|
114 |
+ r->m_channelTimestamp[r->m_mediaChannel]; |
|
115 |
+ if (!RTMP_SendPause(r, pause, r->m_pauseStamp)) |
|
116 |
+ return -1; |
|
117 |
+ return 0; |
|
118 |
+} |
|
119 |
+ |
|
120 |
+static int64_t rtmp_read_seek(URLContext *s, int stream_index, |
|
121 |
+ int64_t timestamp, int flags) |
|
122 |
+{ |
|
123 |
+ RTMP *r = s->priv_data; |
|
124 |
+ |
|
125 |
+ if (flags & AVSEEK_FLAG_BYTE) |
|
126 |
+ return AVERROR_NOTSUPP; |
|
127 |
+ |
|
128 |
+ /* seeks are in milliseconds */ |
|
129 |
+ timestamp = av_rescale(timestamp, AV_TIME_BASE, 1000); |
|
130 |
+ if (!RTMP_SendSeek(r, timestamp)) |
|
131 |
+ return -1; |
|
132 |
+ return timestamp; |
|
133 |
+} |
|
134 |
+ |
|
135 |
+static int rtmp_get_file_handle(URLContext *s) |
|
136 |
+{ |
|
137 |
+ RTMP *r = s->priv_data; |
|
138 |
+ |
|
139 |
+ return r->m_sb.sb_socket; |
|
140 |
+} |
|
141 |
+ |
|
142 |
+URLProtocol rtmp_protocol = { |
|
143 |
+ "rtmp", |
|
144 |
+ rtmp_open, |
|
145 |
+ rtmp_read, |
|
146 |
+ rtmp_write, |
|
147 |
+ NULL, /* seek */ |
|
148 |
+ rtmp_close, |
|
149 |
+ NULL, /* next */ |
|
150 |
+ rtmp_read_pause, |
|
151 |
+ rtmp_read_seek, |
|
152 |
+ rtmp_get_file_handle |
|
153 |
+}; |
|
154 |
+ |
|
155 |
+URLProtocol rtmpt_protocol = { |
|
156 |
+ "rtmpt", |
|
157 |
+ rtmp_open, |
|
158 |
+ rtmp_read, |
|
159 |
+ rtmp_write, |
|
160 |
+ NULL, /* seek */ |
|
161 |
+ rtmp_close, |
|
162 |
+ NULL, /* next */ |
|
163 |
+ rtmp_read_pause, |
|
164 |
+ rtmp_read_seek, |
|
165 |
+ rtmp_get_file_handle |
|
166 |
+}; |
|
167 |
+ |
|
168 |
+URLProtocol rtmpe_protocol = { |
|
169 |
+ "rtmpe", |
|
170 |
+ rtmp_open, |
|
171 |
+ rtmp_read, |
|
172 |
+ rtmp_write, |
|
173 |
+ NULL, /* seek */ |
|
174 |
+ rtmp_close, |
|
175 |
+ NULL, /* next */ |
|
176 |
+ rtmp_read_pause, |
|
177 |
+ rtmp_read_seek, |
|
178 |
+ rtmp_get_file_handle |
|
179 |
+}; |
|
180 |
+ |
|
181 |
+URLProtocol rtmpte_protocol = { |
|
182 |
+ "rtmpte", |
|
183 |
+ rtmp_open, |
|
184 |
+ rtmp_read, |
|
185 |
+ rtmp_write, |
|
186 |
+ NULL, /* seek */ |
|
187 |
+ rtmp_close, |
|
188 |
+ NULL, /* next */ |
|
189 |
+ rtmp_read_pause, |
|
190 |
+ rtmp_read_seek, |
|
191 |
+ rtmp_get_file_handle |
|
192 |
+}; |
|
193 |
+ |
|
194 |
+URLProtocol rtmps_protocol = { |
|
195 |
+ "rtmps", |
|
196 |
+ rtmp_open, |
|
197 |
+ rtmp_read, |
|
198 |
+ rtmp_write, |
|
199 |
+ NULL, /* seek */ |
|
200 |
+ rtmp_close, |
|
201 |
+ NULL, /* next */ |
|
202 |
+ rtmp_read_pause, |
|
203 |
+ rtmp_read_seek, |
|
204 |
+ rtmp_get_file_handle |
|
205 |
+}; |