Originally committed as revision 25600 to svn://svn.ffmpeg.org/ffmpeg/trunk
Martin Storsjö authored on 2010/10/29 17:41:49... | ... |
@@ -1269,78 +1269,6 @@ static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply |
1269 | 1269 |
static int rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply); |
1270 | 1270 |
#endif /* !CONFIG_RTSP_DEMUXER */ |
1271 | 1271 |
|
1272 |
-#if CONFIG_RTSP_MUXER |
|
1273 |
-static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr) |
|
1274 |
-{ |
|
1275 |
- RTSPState *rt = s->priv_data; |
|
1276 |
- RTSPMessageHeader reply1, *reply = &reply1; |
|
1277 |
- int i; |
|
1278 |
- char *sdp; |
|
1279 |
- AVFormatContext sdp_ctx, *ctx_array[1]; |
|
1280 |
- |
|
1281 |
- s->start_time_realtime = av_gettime(); |
|
1282 |
- |
|
1283 |
- /* Announce the stream */ |
|
1284 |
- sdp = av_mallocz(SDP_MAX_SIZE); |
|
1285 |
- if (sdp == NULL) |
|
1286 |
- return AVERROR(ENOMEM); |
|
1287 |
- /* We create the SDP based on the RTSP AVFormatContext where we |
|
1288 |
- * aren't allowed to change the filename field. (We create the SDP |
|
1289 |
- * based on the RTSP context since the contexts for the RTP streams |
|
1290 |
- * don't exist yet.) In order to specify a custom URL with the actual |
|
1291 |
- * peer IP instead of the originally specified hostname, we create |
|
1292 |
- * a temporary copy of the AVFormatContext, where the custom URL is set. |
|
1293 |
- * |
|
1294 |
- * FIXME: Create the SDP without copying the AVFormatContext. |
|
1295 |
- * This either requires setting up the RTP stream AVFormatContexts |
|
1296 |
- * already here (complicating things immensely) or getting a more |
|
1297 |
- * flexible SDP creation interface. |
|
1298 |
- */ |
|
1299 |
- sdp_ctx = *s; |
|
1300 |
- ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename), |
|
1301 |
- "rtsp", NULL, addr, -1, NULL); |
|
1302 |
- ctx_array[0] = &sdp_ctx; |
|
1303 |
- if (avf_sdp_create(ctx_array, 1, sdp, SDP_MAX_SIZE)) { |
|
1304 |
- av_free(sdp); |
|
1305 |
- return AVERROR_INVALIDDATA; |
|
1306 |
- } |
|
1307 |
- av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); |
|
1308 |
- ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri, |
|
1309 |
- "Content-Type: application/sdp\r\n", |
|
1310 |
- reply, NULL, sdp, strlen(sdp)); |
|
1311 |
- av_free(sdp); |
|
1312 |
- if (reply->status_code != RTSP_STATUS_OK) |
|
1313 |
- return AVERROR_INVALIDDATA; |
|
1314 |
- |
|
1315 |
- /* Set up the RTSPStreams for each AVStream */ |
|
1316 |
- for (i = 0; i < s->nb_streams; i++) { |
|
1317 |
- RTSPStream *rtsp_st; |
|
1318 |
- AVStream *st = s->streams[i]; |
|
1319 |
- |
|
1320 |
- rtsp_st = av_mallocz(sizeof(RTSPStream)); |
|
1321 |
- if (!rtsp_st) |
|
1322 |
- return AVERROR(ENOMEM); |
|
1323 |
- dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); |
|
1324 |
- |
|
1325 |
- st->priv_data = rtsp_st; |
|
1326 |
- rtsp_st->stream_index = i; |
|
1327 |
- |
|
1328 |
- av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url)); |
|
1329 |
- /* Note, this must match the relative uri set in the sdp content */ |
|
1330 |
- av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url), |
|
1331 |
- "/streamid=%d", i); |
|
1332 |
- } |
|
1333 |
- |
|
1334 |
- return 0; |
|
1335 |
-} |
|
1336 |
-#else /* !CONFIG_RTSP_MUXER */ |
|
1337 |
-/* A declaration of this function is needed so that the function is |
|
1338 |
- * defined when parsing the call to it, even if dead code elimination |
|
1339 |
- * will remove the call later. |
|
1340 |
- */ |
|
1341 |
-static int rtsp_setup_output_streams(AVFormatContext *s, const char *addr); |
|
1342 |
-#endif /* !CONFIG_RTSP_MUXER */ |
|
1343 |
- |
|
1344 | 1272 |
void ff_rtsp_close_connections(AVFormatContext *s) |
1345 | 1273 |
{ |
1346 | 1274 |
RTSPState *rt = s->priv_data; |
... | ... |
@@ -1559,7 +1487,7 @@ redirect: |
1559 | 1559 |
if (s->iformat && CONFIG_RTSP_DEMUXER) |
1560 | 1560 |
err = rtsp_setup_input_streams(s, reply); |
1561 | 1561 |
else if (CONFIG_RTSP_MUXER) |
1562 |
- err = rtsp_setup_output_streams(s, host); |
|
1562 |
+ err = ff_rtsp_setup_output_streams(s, host); |
|
1563 | 1563 |
if (err) |
1564 | 1564 |
goto fail; |
1565 | 1565 |
|
... | ... |
@@ -468,4 +468,10 @@ void ff_rtsp_close_streams(AVFormatContext *s); |
468 | 468 |
*/ |
469 | 469 |
void ff_rtsp_close_connections(AVFormatContext *rt); |
470 | 470 |
|
471 |
+/** |
|
472 |
+ * Announce the stream to the server and set up the RTSPStream child |
|
473 |
+ * objects for each media stream. |
|
474 |
+ */ |
|
475 |
+int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr); |
|
476 |
+ |
|
471 | 477 |
#endif /* AVFORMAT_RTSP_H */ |
... | ... |
@@ -29,6 +29,73 @@ |
29 | 29 |
#include "rtsp.h" |
30 | 30 |
#include "internal.h" |
31 | 31 |
#include "libavutil/intreadwrite.h" |
32 |
+#include "libavutil/avstring.h" |
|
33 |
+ |
|
34 |
+#define SDP_MAX_SIZE 16384 |
|
35 |
+ |
|
36 |
+int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) |
|
37 |
+{ |
|
38 |
+ RTSPState *rt = s->priv_data; |
|
39 |
+ RTSPMessageHeader reply1, *reply = &reply1; |
|
40 |
+ int i; |
|
41 |
+ char *sdp; |
|
42 |
+ AVFormatContext sdp_ctx, *ctx_array[1]; |
|
43 |
+ |
|
44 |
+ s->start_time_realtime = av_gettime(); |
|
45 |
+ |
|
46 |
+ /* Announce the stream */ |
|
47 |
+ sdp = av_mallocz(SDP_MAX_SIZE); |
|
48 |
+ if (sdp == NULL) |
|
49 |
+ return AVERROR(ENOMEM); |
|
50 |
+ /* We create the SDP based on the RTSP AVFormatContext where we |
|
51 |
+ * aren't allowed to change the filename field. (We create the SDP |
|
52 |
+ * based on the RTSP context since the contexts for the RTP streams |
|
53 |
+ * don't exist yet.) In order to specify a custom URL with the actual |
|
54 |
+ * peer IP instead of the originally specified hostname, we create |
|
55 |
+ * a temporary copy of the AVFormatContext, where the custom URL is set. |
|
56 |
+ * |
|
57 |
+ * FIXME: Create the SDP without copying the AVFormatContext. |
|
58 |
+ * This either requires setting up the RTP stream AVFormatContexts |
|
59 |
+ * already here (complicating things immensely) or getting a more |
|
60 |
+ * flexible SDP creation interface. |
|
61 |
+ */ |
|
62 |
+ sdp_ctx = *s; |
|
63 |
+ ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename), |
|
64 |
+ "rtsp", NULL, addr, -1, NULL); |
|
65 |
+ ctx_array[0] = &sdp_ctx; |
|
66 |
+ if (avf_sdp_create(ctx_array, 1, sdp, SDP_MAX_SIZE)) { |
|
67 |
+ av_free(sdp); |
|
68 |
+ return AVERROR_INVALIDDATA; |
|
69 |
+ } |
|
70 |
+ av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); |
|
71 |
+ ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri, |
|
72 |
+ "Content-Type: application/sdp\r\n", |
|
73 |
+ reply, NULL, sdp, strlen(sdp)); |
|
74 |
+ av_free(sdp); |
|
75 |
+ if (reply->status_code != RTSP_STATUS_OK) |
|
76 |
+ return AVERROR_INVALIDDATA; |
|
77 |
+ |
|
78 |
+ /* Set up the RTSPStreams for each AVStream */ |
|
79 |
+ for (i = 0; i < s->nb_streams; i++) { |
|
80 |
+ RTSPStream *rtsp_st; |
|
81 |
+ AVStream *st = s->streams[i]; |
|
82 |
+ |
|
83 |
+ rtsp_st = av_mallocz(sizeof(RTSPStream)); |
|
84 |
+ if (!rtsp_st) |
|
85 |
+ return AVERROR(ENOMEM); |
|
86 |
+ dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); |
|
87 |
+ |
|
88 |
+ st->priv_data = rtsp_st; |
|
89 |
+ rtsp_st->stream_index = i; |
|
90 |
+ |
|
91 |
+ av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url)); |
|
92 |
+ /* Note, this must match the relative uri set in the sdp content */ |
|
93 |
+ av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url), |
|
94 |
+ "/streamid=%d", i); |
|
95 |
+ } |
|
96 |
+ |
|
97 |
+ return 0; |
|
98 |
+} |
|
32 | 99 |
|
33 | 100 |
static int rtsp_write_record(AVFormatContext *s) |
34 | 101 |
{ |