annotate rtmpproto.c @ 6142:bd851edc58ac libavformat

RTMP: Return from rtmp_read as soon as some data is available Earlier, the function only returned when the enough data to fill the requested buffer was available. This lead to high latency when receiving low-bandwidth streams.
author mstorsjo
date Fri, 18 Jun 2010 12:02:51 +0000
parents 7fdda2416684
children 4fc5e0e4e1cd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
1 /*
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
2 * RTMP network protocol
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
3 * Copyright (c) 2009 Kostya Shishkov
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
4 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
5 * This file is part of FFmpeg.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
6 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
11 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
15 * Lesser General Public License for more details.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
16 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
20 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
21
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
22 /**
5969
178de7695c6c Remove explicit filename from Doxygen @file commands.
diego
parents: 5837
diff changeset
23 * @file
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
24 * RTMP protocol
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
25 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
26
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
27 #include "libavcodec/bytestream.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
28 #include "libavutil/avstring.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
29 #include "libavutil/lfg.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
30 #include "libavutil/sha.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
31 #include "avformat.h"
5837
d605f589f0be move ff_url_split() and ff_url_join() declarations to internal.h
aurel
parents: 5776
diff changeset
32 #include "internal.h"
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
33
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
34 #include "network.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
35
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
36 #include "flv.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
37 #include "rtmp.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
38 #include "rtmppkt.h"
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
39
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
40 /* we can't use av_log() with URLContext yet... */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
41 #if LIBAVFORMAT_VERSION_MAJOR < 53
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
42 #define LOG_CONTEXT NULL
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
43 #else
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
44 #define LOG_CONTEXT s
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
45 #endif
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
46
5432
f282f7758d6e Dump RTMP packet contents in debug mode
kostya
parents: 5431
diff changeset
47 //#define DEBUG
f282f7758d6e Dump RTMP packet contents in debug mode
kostya
parents: 5431
diff changeset
48
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
49 /** RTMP protocol handler state */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
50 typedef enum {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
51 STATE_START, ///< client has not done anything yet
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
52 STATE_HANDSHAKED, ///< client has performed handshake
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
53 STATE_RELEASING, ///< client releasing stream before publish it (for output)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
54 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
55 STATE_CONNECTING, ///< client connected to server successfully
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
56 STATE_READY, ///< client has sent all needed commands and waits for server reply
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
57 STATE_PLAYING, ///< client has started receiving multimedia data from server
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
58 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
5430
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
59 STATE_STOPPED, ///< the broadcast has been stopped
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
60 } ClientState;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
61
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
62 /** protocol handler context */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
63 typedef struct RTMPContext {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
64 URLContext* stream; ///< TCP stream used in interactions with RTMP server
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
65 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
66 int chunk_size; ///< size of the chunks RTMP packets are divided into
5407
b7ef0aa415d0 Move is_input flag into RTMP protocol context.
kostya
parents: 5402
diff changeset
67 int is_input; ///< input/output flag
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
68 char playpath[256]; ///< path to filename to play (with possible "mp4:" prefix)
5411
1f27e6bd85c3 Move "app" string into RTMP protocol context.
kostya
parents: 5407
diff changeset
69 char app[128]; ///< application
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
70 ClientState state; ///< current state
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
71 int main_channel_id; ///< an additional channel ID which is used for some invocations
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
72 uint8_t* flv_data; ///< buffer with data for demuxer
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
73 int flv_size; ///< current buffer size
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
74 int flv_off; ///< number of bytes read from current buffer
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
75 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
5668
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
76 uint32_t client_report_size; ///< number of bytes after which client should report to server
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
77 uint32_t bytes_read; ///< number of bytes read from server
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
78 uint32_t last_bytes_read; ///< number of bytes read last reported to server
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
79 } RTMPContext;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
80
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
81 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
82 /** Client key used for digest signing */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
83 static const uint8_t rtmp_player_key[] = {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
84 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
85 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
86
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
87 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
88 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
89 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
90 };
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
91
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
92 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
93 /** Key used for RTMP server digest signing */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
94 static const uint8_t rtmp_server_key[] = {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
95 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
96 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
97 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
98
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
99 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
100 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
101 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
102 };
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
103
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
104 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
105 * Generates 'connect' call and sends it to the server.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
106 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
107 static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto,
5411
1f27e6bd85c3 Move "app" string into RTMP protocol context.
kostya
parents: 5407
diff changeset
108 const char *host, int port)
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
109 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
110 RTMPPacket pkt;
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
111 uint8_t ver[64], *p;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
112 char tcurl[512];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
113
5412
95bc775d22ff Send connect() and createStream() in RTMP system channel, not video channel.
kostya
parents: 5411
diff changeset
114 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
115 p = pkt.data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
116
5756
7c7fe75728dd Use ff_url_join for assembling URLs, instead of snprintf
mstorsjo
parents: 5668
diff changeset
117 ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
118 ff_amf_write_string(&p, "connect");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
119 ff_amf_write_number(&p, 1.0);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
120 ff_amf_write_object_start(&p);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
121 ff_amf_write_field_name(&p, "app");
5411
1f27e6bd85c3 Move "app" string into RTMP protocol context.
kostya
parents: 5407
diff changeset
122 ff_amf_write_string(&p, rt->app);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
123
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
124 if (rt->is_input) {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
125 snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
126 RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
127 } else {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
128 snprintf(ver, sizeof(ver), "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
129 ff_amf_write_field_name(&p, "type");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
130 ff_amf_write_string(&p, "nonprivate");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
131 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
132 ff_amf_write_field_name(&p, "flashVer");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
133 ff_amf_write_string(&p, ver);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
134 ff_amf_write_field_name(&p, "tcUrl");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
135 ff_amf_write_string(&p, tcurl);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
136 if (rt->is_input) {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
137 ff_amf_write_field_name(&p, "fpad");
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
138 ff_amf_write_bool(&p, 0);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
139 ff_amf_write_field_name(&p, "capabilities");
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
140 ff_amf_write_number(&p, 15.0);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
141 ff_amf_write_field_name(&p, "audioCodecs");
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
142 ff_amf_write_number(&p, 1639.0);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
143 ff_amf_write_field_name(&p, "videoCodecs");
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
144 ff_amf_write_number(&p, 252.0);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
145 ff_amf_write_field_name(&p, "videoFunction");
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
146 ff_amf_write_number(&p, 1.0);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
147 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
148 ff_amf_write_object_end(&p);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
149
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
150 pkt.data_size = p - pkt.data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
151
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
152 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
5431
b0eb87793222 5l trocadero: don't forget to free packet in gen_connect()
kostya
parents: 5430
diff changeset
153 ff_rtmp_packet_destroy(&pkt);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
154 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
155
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
156 /**
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
157 * Generates 'releaseStream' call and sends it to the server. It should make
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
158 * the server release some channel for media streams.
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
159 */
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
160 static void gen_release_stream(URLContext *s, RTMPContext *rt)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
161 {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
162 RTMPPacket pkt;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
163 uint8_t *p;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
164
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
165 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
166 29 + strlen(rt->playpath));
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
167
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
168 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Releasing stream...\n");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
169 p = pkt.data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
170 ff_amf_write_string(&p, "releaseStream");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
171 ff_amf_write_number(&p, 2.0);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
172 ff_amf_write_null(&p);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
173 ff_amf_write_string(&p, rt->playpath);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
174
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
175 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
176 ff_rtmp_packet_destroy(&pkt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
177 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
178
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
179 /**
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
180 * Generates 'FCPublish' call and sends it to the server. It should make
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
181 * the server preapare for receiving media streams.
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
182 */
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
183 static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
184 {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
185 RTMPPacket pkt;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
186 uint8_t *p;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
187
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
188 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
189 25 + strlen(rt->playpath));
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
190
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
191 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FCPublish stream...\n");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
192 p = pkt.data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
193 ff_amf_write_string(&p, "FCPublish");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
194 ff_amf_write_number(&p, 3.0);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
195 ff_amf_write_null(&p);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
196 ff_amf_write_string(&p, rt->playpath);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
197
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
198 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
199 ff_rtmp_packet_destroy(&pkt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
200 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
201
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
202 /**
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
203 * Generates 'FCUnpublish' call and sends it to the server. It should make
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
204 * the server destroy stream.
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
205 */
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
206 static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
207 {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
208 RTMPPacket pkt;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
209 uint8_t *p;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
210
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
211 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
212 27 + strlen(rt->playpath));
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
213
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
214 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "UnPublishing stream...\n");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
215 p = pkt.data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
216 ff_amf_write_string(&p, "FCUnpublish");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
217 ff_amf_write_number(&p, 5.0);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
218 ff_amf_write_null(&p);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
219 ff_amf_write_string(&p, rt->playpath);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
220
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
221 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
222 ff_rtmp_packet_destroy(&pkt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
223 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
224
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
225 /**
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
226 * Generates 'createStream' call and sends it to the server. It should make
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
227 * the server allocate some channel for media streams.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
228 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
229 static void gen_create_stream(URLContext *s, RTMPContext *rt)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
230 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
231 RTMPPacket pkt;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
232 uint8_t *p;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
233
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
234 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Creating stream...\n");
5412
95bc775d22ff Send connect() and createStream() in RTMP system channel, not video channel.
kostya
parents: 5411
diff changeset
235 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
236
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
237 p = pkt.data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
238 ff_amf_write_string(&p, "createStream");
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
239 ff_amf_write_number(&p, rt->is_input ? 3.0 : 4.0);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
240 ff_amf_write_null(&p);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
241
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
242 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
243 ff_rtmp_packet_destroy(&pkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
244 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
245
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
246
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
247 /**
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
248 * Generates 'deleteStream' call and sends it to the server. It should make
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
249 * the server remove some channel for media streams.
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
250 */
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
251 static void gen_delete_stream(URLContext *s, RTMPContext *rt)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
252 {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
253 RTMPPacket pkt;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
254 uint8_t *p;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
255
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
256 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Deleting stream...\n");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
257 ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
258
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
259 p = pkt.data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
260 ff_amf_write_string(&p, "deleteStream");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
261 ff_amf_write_number(&p, 0.0);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
262 ff_amf_write_null(&p);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
263 ff_amf_write_number(&p, rt->main_channel_id);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
264
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
265 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
266 ff_rtmp_packet_destroy(&pkt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
267 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
268
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
269 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
270 * Generates 'play' call and sends it to the server, then pings the server
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
271 * to start actual playing.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
272 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
273 static void gen_play(URLContext *s, RTMPContext *rt)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
274 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
275 RTMPPacket pkt;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
276 uint8_t *p;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
277
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
278 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
279 ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
5295
08ec48911f20 Last parameter in RTMP "play" call was optional and some servers seem not to
kostya
parents: 5214
diff changeset
280 20 + strlen(rt->playpath));
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
281 pkt.extra = rt->main_channel_id;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
282
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
283 p = pkt.data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
284 ff_amf_write_string(&p, "play");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
285 ff_amf_write_number(&p, 0.0);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
286 ff_amf_write_null(&p);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
287 ff_amf_write_string(&p, rt->playpath);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
288
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
289 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
290 ff_rtmp_packet_destroy(&pkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
291
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
292 // set client buffer time disguised in ping packet
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
293 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
294
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
295 p = pkt.data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
296 bytestream_put_be16(&p, 3);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
297 bytestream_put_be32(&p, 1);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
298 bytestream_put_be32(&p, 256); //TODO: what is a good value here?
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
299
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
300 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
301 ff_rtmp_packet_destroy(&pkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
302 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
303
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
304 /**
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
305 * Generates 'publish' call and sends it to the server.
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
306 */
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
307 static void gen_publish(URLContext *s, RTMPContext *rt)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
308 {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
309 RTMPPacket pkt;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
310 uint8_t *p;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
311
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
312 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
313 ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
314 30 + strlen(rt->playpath));
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
315 pkt.extra = rt->main_channel_id;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
316
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
317 p = pkt.data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
318 ff_amf_write_string(&p, "publish");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
319 ff_amf_write_number(&p, 0.0);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
320 ff_amf_write_null(&p);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
321 ff_amf_write_string(&p, rt->playpath);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
322 ff_amf_write_string(&p, "live");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
323
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
324 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
325 ff_rtmp_packet_destroy(&pkt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
326 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
327
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
328 /**
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
329 * Generates ping reply and sends it to the server.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
330 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
331 static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
332 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
333 RTMPPacket pkt;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
334 uint8_t *p;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
335
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
336 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
337 p = pkt.data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
338 bytestream_put_be16(&p, 7);
5465
4ee5aa5e013c Reply to RTMP ping with the same value as received by client.
kostya
parents: 5432
diff changeset
339 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
340 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
341 ff_rtmp_packet_destroy(&pkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
342 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
343
5668
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
344 /**
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
345 * Generates report on bytes read so far and sends it to the server.
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
346 */
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
347 static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
348 {
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
349 RTMPPacket pkt;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
350 uint8_t *p;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
351
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
352 ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
353 p = pkt.data;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
354 bytestream_put_be32(&p, rt->bytes_read);
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
355 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
356 ff_rtmp_packet_destroy(&pkt);
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
357 }
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
358
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
359 //TODO: Move HMAC code somewhere. Eventually.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
360 #define HMAC_IPAD_VAL 0x36
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
361 #define HMAC_OPAD_VAL 0x5C
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
362
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
363 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
364 * Calculates HMAC-SHA2 digest for RTMP handshake packets.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
365 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
366 * @param src input buffer
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
367 * @param len input buffer length (should be 1536)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
368 * @param gap offset in buffer where 32 bytes should not be taken into account
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
369 * when calculating digest (since it will be used to store that digest)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
370 * @param key digest key
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
371 * @param keylen digest key length
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
372 * @param dst buffer where calculated digest will be stored (32 bytes)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
373 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
374 static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
375 const uint8_t *key, int keylen, uint8_t *dst)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
376 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
377 struct AVSHA *sha;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
378 uint8_t hmac_buf[64+32] = {0};
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
379 int i;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
380
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
381 sha = av_mallocz(av_sha_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
382
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
383 if (keylen < 64) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
384 memcpy(hmac_buf, key, keylen);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
385 } else {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
386 av_sha_init(sha, 256);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
387 av_sha_update(sha,key, keylen);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
388 av_sha_final(sha, hmac_buf);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
389 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
390 for (i = 0; i < 64; i++)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
391 hmac_buf[i] ^= HMAC_IPAD_VAL;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
392
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
393 av_sha_init(sha, 256);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
394 av_sha_update(sha, hmac_buf, 64);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
395 if (gap <= 0) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
396 av_sha_update(sha, src, len);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
397 } else { //skip 32 bytes used for storing digest
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
398 av_sha_update(sha, src, gap);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
399 av_sha_update(sha, src + gap + 32, len - gap - 32);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
400 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
401 av_sha_final(sha, hmac_buf + 64);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
402
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
403 for (i = 0; i < 64; i++)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
404 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
405 av_sha_init(sha, 256);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
406 av_sha_update(sha, hmac_buf, 64+32);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
407 av_sha_final(sha, dst);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
408
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
409 av_free(sha);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
410 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
411
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
412 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
413 * Puts HMAC-SHA2 digest of packet data (except for the bytes where this digest
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
414 * will be stored) into that packet.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
415 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
416 * @param buf handshake data (1536 bytes)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
417 * @return offset to the digest inside input data
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
418 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
419 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
420 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
421 int i, digest_pos = 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
422
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
423 for (i = 8; i < 12; i++)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
424 digest_pos += buf[i];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
425 digest_pos = (digest_pos % 728) + 12;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
426
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
427 rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
428 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
429 buf + digest_pos);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
430 return digest_pos;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
431 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
432
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
433 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
434 * Verifies that the received server response has the expected digest value.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
435 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
436 * @param buf handshake data received from the server (1536 bytes)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
437 * @param off position to search digest offset from
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
438 * @return 0 if digest is valid, digest position otherwise
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
439 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
440 static int rtmp_validate_digest(uint8_t *buf, int off)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
441 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
442 int i, digest_pos = 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
443 uint8_t digest[32];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
444
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
445 for (i = 0; i < 4; i++)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
446 digest_pos += buf[i + off];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
447 digest_pos = (digest_pos % 728) + off + 4;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
448
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
449 rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
450 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
451 digest);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
452 if (!memcmp(digest, buf + digest_pos, 32))
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
453 return digest_pos;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
454 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
455 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
456
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
457 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
458 * Performs handshake with the server by means of exchanging pseudorandom data
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
459 * signed with HMAC-SHA2 digest.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
460 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
461 * @return 0 if handshake succeeds, negative value otherwise
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
462 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
463 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
464 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
465 AVLFG rnd;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
466 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
467 3, // unencrypted data
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
468 0, 0, 0, 0, // client uptime
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
469 RTMP_CLIENT_VER1,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
470 RTMP_CLIENT_VER2,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
471 RTMP_CLIENT_VER3,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
472 RTMP_CLIENT_VER4,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
473 };
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
474 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
475 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
476 int i;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
477 int server_pos, client_pos;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
478 uint8_t digest[32];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
479
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
480 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Handshaking...\n");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
481
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
482 av_lfg_init(&rnd, 0xDEADC0DE);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
483 // generate handshake packet - 1536 bytes of pseudorandom data
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
484 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
485 tosend[i] = av_lfg_get(&rnd) >> 24;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
486 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
487
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
488 url_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
489 i = url_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
490 if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
491 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
492 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
493 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
494 i = url_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
495 if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
496 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
497 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
498 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
499
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
500 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
501 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
502
5523
d854655b2042 Use old-style RTMP handshake for old servers.
kostya
parents: 5465
diff changeset
503 if (rt->is_input && serverdata[5] >= 3) {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
504 server_pos = rtmp_validate_digest(serverdata + 1, 772);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
505 if (!server_pos) {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
506 server_pos = rtmp_validate_digest(serverdata + 1, 8);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
507 if (!server_pos) {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
508 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server response validating failed\n");
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
509 return -1;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
510 }
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
511 }
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
512
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
513 rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
514 rtmp_server_key, sizeof(rtmp_server_key),
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
515 digest);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
516 rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
517 digest, 32,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
518 digest);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
519 if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
520 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Signature mismatch\n");
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
521 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
522 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
523
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
524 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
525 tosend[i] = av_lfg_get(&rnd) >> 24;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
526 rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
527 rtmp_player_key, sizeof(rtmp_player_key),
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
528 digest);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
529 rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
530 digest, 32,
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
531 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
532
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
533 // write reply back to the server
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
534 url_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
535 } else {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
536 url_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
537 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
538
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
539 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
540 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
541
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
542 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
543 * Parses received packet and may perform some action depending on
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
544 * the packet contents.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
545 * @return 0 for no errors, negative values for serious errors which prevent
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
546 * further communications, positive values for uncritical errors
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
547 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
548 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
549 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
550 int i, t;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
551 const uint8_t *data_end = pkt->data + pkt->data_size;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
552
5432
f282f7758d6e Dump RTMP packet contents in debug mode
kostya
parents: 5431
diff changeset
553 #ifdef DEBUG
f282f7758d6e Dump RTMP packet contents in debug mode
kostya
parents: 5431
diff changeset
554 ff_rtmp_packet_dump(LOG_CONTEXT, pkt);
f282f7758d6e Dump RTMP packet contents in debug mode
kostya
parents: 5431
diff changeset
555 #endif
f282f7758d6e Dump RTMP packet contents in debug mode
kostya
parents: 5431
diff changeset
556
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
557 switch (pkt->type) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
558 case RTMP_PT_CHUNK_SIZE:
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
559 if (pkt->data_size != 4) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
560 av_log(LOG_CONTEXT, AV_LOG_ERROR,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
561 "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
562 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
563 }
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
564 if (!rt->is_input)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
565 ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
566 rt->chunk_size = AV_RB32(pkt->data);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
567 if (rt->chunk_size <= 0) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
568 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
569 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
570 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
571 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
572 break;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
573 case RTMP_PT_PING:
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
574 t = AV_RB16(pkt->data);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
575 if (t == 6)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
576 gen_pong(s, rt, pkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
577 break;
5668
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
578 case RTMP_PT_CLIENT_BW:
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
579 if (pkt->data_size < 4) {
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
580 av_log(LOG_CONTEXT, AV_LOG_ERROR,
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
581 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
582 pkt->data_size);
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
583 return -1;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
584 }
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
585 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
586 rt->client_report_size = AV_RB32(pkt->data) >> 1;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
587 break;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
588 case RTMP_PT_INVOKE:
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
589 //TODO: check for the messages sent for wrong state?
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
590 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
591 uint8_t tmpstr[256];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
592
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
593 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
594 "description", tmpstr, sizeof(tmpstr)))
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
595 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
596 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
597 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
598 switch (rt->state) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
599 case STATE_HANDSHAKED:
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
600 if (!rt->is_input) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
601 gen_release_stream(s, rt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
602 gen_fcpublish_stream(s, rt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
603 rt->state = STATE_RELEASING;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
604 } else {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
605 rt->state = STATE_CONNECTING;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
606 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
607 gen_create_stream(s, rt);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
608 break;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
609 case STATE_FCPUBLISH:
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
610 rt->state = STATE_CONNECTING;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
611 break;
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
612 case STATE_RELEASING:
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
613 rt->state = STATE_FCPUBLISH;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
614 /* hack for Wowza Media Server, it does not send result for
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
615 * releaseStream and FCPublish calls */
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
616 if (!pkt->data[10]) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
617 int pkt_id = (int) av_int2dbl(AV_RB64(pkt->data + 11));
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
618 if (pkt_id == 4)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
619 rt->state = STATE_CONNECTING;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
620 }
5420
62329840eb7c cosmetics: insert space between codeword and left parenthesis
kostya
parents: 5419
diff changeset
621 if (rt->state != STATE_CONNECTING)
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
622 break;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
623 case STATE_CONNECTING:
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
624 //extract a number from the result
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
625 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
626 av_log(LOG_CONTEXT, AV_LOG_WARNING, "Unexpected reply on connect()\n");
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
627 } else {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
628 rt->main_channel_id = (int) av_int2dbl(AV_RB64(pkt->data + 21));
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
629 }
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
630 if (rt->is_input) {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
631 gen_play(s, rt);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
632 } else {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
633 gen_publish(s, rt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
634 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
635 rt->state = STATE_READY;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
636 break;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
637 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
638 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
639 const uint8_t* ptr = pkt->data + 11;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
640 uint8_t tmpstr[256];
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
641
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
642 for (i = 0; i < 2; i++) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
643 t = ff_amf_tag_size(ptr, data_end);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
644 if (t < 0)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
645 return 1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
646 ptr += t;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
647 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
648 t = ff_amf_get_field_value(ptr, data_end,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
649 "level", tmpstr, sizeof(tmpstr));
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
650 if (!t && !strcmp(tmpstr, "error")) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
651 if (!ff_amf_get_field_value(ptr, data_end,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
652 "description", tmpstr, sizeof(tmpstr)))
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
653 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
654 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
655 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
656 t = ff_amf_get_field_value(ptr, data_end,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
657 "code", tmpstr, sizeof(tmpstr));
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
658 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
5430
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
659 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
660 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
661 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
662 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
663 break;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
664 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
665 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
666 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
667
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
668 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
669 * Interacts with the server by receiving and sending RTMP packets until
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
670 * there is some significant data (media data or expected status notification).
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
671 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
672 * @param s reading context
5367
f0711d97bff4 Split overly long line in doxy.
stefano
parents: 5295
diff changeset
673 * @param for_header non-zero value tells function to work until it
f0711d97bff4 Split overly long line in doxy.
stefano
parents: 5295
diff changeset
674 * gets notification from the server that playing has been started,
f0711d97bff4 Split overly long line in doxy.
stefano
parents: 5295
diff changeset
675 * otherwise function will work until some media data is received (or
f0711d97bff4 Split overly long line in doxy.
stefano
parents: 5295
diff changeset
676 * an error happens)
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
677 * @return 0 for successful operation, negative value in case of error
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
678 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
679 static int get_packet(URLContext *s, int for_header)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
680 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
681 RTMPContext *rt = s->priv_data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
682 int ret;
5524
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
683 uint8_t *p;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
684 const uint8_t *next;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
685 uint32_t data_size;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
686 uint32_t ts, cts, pts=0;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
687
5430
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
688 if (rt->state == STATE_STOPPED)
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
689 return AVERROR_EOF;
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
690
5420
62329840eb7c cosmetics: insert space between codeword and left parenthesis
kostya
parents: 5419
diff changeset
691 for (;;) {
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
692 RTMPPacket rpkt;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
693 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
5606
2023dcca33ff another 10l: forgot to change parent condition as well
kostya
parents: 5605
diff changeset
694 rt->chunk_size, rt->prev_pkt[0])) <= 0) {
5605
32fe8ab7e6b6 10l trocadero: now return value of ff_rtmp_packet_read() has different meaning
kostya
parents: 5524
diff changeset
695 if (ret == 0) {
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
696 return AVERROR(EAGAIN);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
697 } else {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
698 return AVERROR(EIO);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
699 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
700 }
5668
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
701 rt->bytes_read += ret;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
702 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
703 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending bytes read report\n");
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
704 gen_bytes_read(s, rt, rpkt.timestamp + 1);
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
705 rt->last_bytes_read = rt->bytes_read;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
706 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
707
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
708 ret = rtmp_parse_result(s, rt, &rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
709 if (ret < 0) {//serious error in current packet
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
710 ff_rtmp_packet_destroy(&rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
711 return -1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
712 }
5430
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
713 if (rt->state == STATE_STOPPED) {
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
714 ff_rtmp_packet_destroy(&rpkt);
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
715 return AVERROR_EOF;
bbfed6be7f29 Do not try to interact with RTMP server after "stop" command was received.
kostya
parents: 5420
diff changeset
716 }
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
717 if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
718 ff_rtmp_packet_destroy(&rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
719 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
720 }
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
721 if (!rpkt.data_size || !rt->is_input) {
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
722 ff_rtmp_packet_destroy(&rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
723 continue;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
724 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
725 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
5376
f31fa4114750 Pass only useful FLV metadata from RTMP stream
kostya
parents: 5367
diff changeset
726 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
5524
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
727 ts = rpkt.timestamp;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
728
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
729 // generate packet header and put data into buffer for FLV demuxer
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
730 rt->flv_off = 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
731 rt->flv_size = rpkt.data_size + 15;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
732 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
733 bytestream_put_byte(&p, rpkt.type);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
734 bytestream_put_be24(&p, rpkt.data_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
735 bytestream_put_be24(&p, ts);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
736 bytestream_put_byte(&p, ts >> 24);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
737 bytestream_put_be24(&p, 0);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
738 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
739 bytestream_put_be32(&p, 0);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
740 ff_rtmp_packet_destroy(&rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
741 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
742 } else if (rpkt.type == RTMP_PT_METADATA) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
743 // we got raw FLV data, make it available for FLV demuxer
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
744 rt->flv_off = 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
745 rt->flv_size = rpkt.data_size;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
746 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
5524
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
747 /* rewrite timestamps */
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
748 next = rpkt.data;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
749 ts = rpkt.timestamp;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
750 while (next - rpkt.data < rpkt.data_size - 11) {
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
751 next++;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
752 data_size = bytestream_get_be24(&next);
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
753 p=next;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
754 cts = bytestream_get_be24(&next);
6055
1e49d06baf93 24l trocadero: RTMP reader forgot to shift high byte of timestamp to its
kostya
parents: 5969
diff changeset
755 cts |= bytestream_get_byte(&next) << 24;
5524
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
756 if (pts==0)
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
757 pts=cts;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
758 ts += cts - pts;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
759 pts = cts;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
760 bytestream_put_be24(&p, ts);
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
761 bytestream_put_byte(&p, ts >> 24);
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
762 next += data_size + 3 + 4;
043b36cefe89 Correct timestamps inside FLV data received by RTMP.
kostya
parents: 5523
diff changeset
763 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
764 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
765 ff_rtmp_packet_destroy(&rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
766 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
767 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
768 ff_rtmp_packet_destroy(&rpkt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
769 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
770 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
771 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
772
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
773 static int rtmp_close(URLContext *h)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
774 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
775 RTMPContext *rt = h->priv_data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
776
5420
62329840eb7c cosmetics: insert space between codeword and left parenthesis
kostya
parents: 5419
diff changeset
777 if (!rt->is_input) {
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
778 rt->flv_data = NULL;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
779 if (rt->out_pkt.data_size)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
780 ff_rtmp_packet_destroy(&rt->out_pkt);
5419
006c95a7a3d2 Do not send invokes to RTMP server if we are not connected to it.
kostya
parents: 5417
diff changeset
781 if (rt->state > STATE_FCPUBLISH)
006c95a7a3d2 Do not send invokes to RTMP server if we are not connected to it.
kostya
parents: 5417
diff changeset
782 gen_fcunpublish_stream(h, rt);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
783 }
5419
006c95a7a3d2 Do not send invokes to RTMP server if we are not connected to it.
kostya
parents: 5417
diff changeset
784 if (rt->state > STATE_HANDSHAKED)
006c95a7a3d2 Do not send invokes to RTMP server if we are not connected to it.
kostya
parents: 5417
diff changeset
785 gen_delete_stream(h, rt);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
786
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
787 av_freep(&rt->flv_data);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
788 url_close(rt->stream);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
789 av_free(rt);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
790 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
791 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
792
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
793 /**
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
794 * Opens RTMP connection and verifies that the stream can be played.
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
795 *
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
796 * URL syntax: rtmp://server[:port][/app][/playpath]
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
797 * where 'app' is first one or two directories in the path
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
798 * (e.g. /ondemand/, /flash/live/, etc.)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
799 * and 'playpath' is a file name (the rest of the path,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
800 * may be prefixed with "mp4:")
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
801 */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
802 static int rtmp_open(URLContext *s, const char *uri, int flags)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
803 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
804 RTMPContext *rt;
5411
1f27e6bd85c3 Move "app" string into RTMP protocol context.
kostya
parents: 5407
diff changeset
805 char proto[8], hostname[256], path[1024], *fname;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
806 uint8_t buf[2048];
5407
b7ef0aa415d0 Move is_input flag into RTMP protocol context.
kostya
parents: 5402
diff changeset
807 int port;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
808 int ret;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
809
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
810 rt = av_mallocz(sizeof(RTMPContext));
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
811 if (!rt)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
812 return AVERROR(ENOMEM);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
813 s->priv_data = rt;
5407
b7ef0aa415d0 Move is_input flag into RTMP protocol context.
kostya
parents: 5402
diff changeset
814 rt->is_input = !(flags & URL_WRONLY);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
815
5775
7a123cc24a81 Rename url_split to ff_url_split
mstorsjo
parents: 5756
diff changeset
816 ff_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
5776
d34f985d6e8f Reindent
mstorsjo
parents: 5775
diff changeset
817 path, sizeof(path), s->filename);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
818
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
819 if (port < 0)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
820 port = RTMP_DEFAULT_PORT;
5756
7c7fe75728dd Use ff_url_join for assembling URLs, instead of snprintf
mstorsjo
parents: 5668
diff changeset
821 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
822
5377
9313acce85fc Print error when RTMP protocol can't open connection
kostya
parents: 5376
diff changeset
823 if (url_open(&rt->stream, buf, URL_RDWR) < 0) {
9313acce85fc Print error when RTMP protocol can't open connection
kostya
parents: 5376
diff changeset
824 av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
825 goto fail;
5377
9313acce85fc Print error when RTMP protocol can't open connection
kostya
parents: 5376
diff changeset
826 }
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
827
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
828 rt->state = STATE_START;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
829 if (rtmp_handshake(s, rt))
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
830 return -1;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
831
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
832 rt->chunk_size = 128;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
833 rt->state = STATE_HANDSHAKED;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
834 //extract "app" part from path
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
835 if (!strncmp(path, "/ondemand/", 10)) {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
836 fname = path + 10;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
837 memcpy(rt->app, "ondemand", 9);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
838 } else {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
839 char *p = strchr(path + 1, '/');
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
840 if (!p) {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
841 fname = path + 1;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
842 rt->app[0] = '\0';
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
843 } else {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
844 char *c = strchr(p + 1, ':');
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
845 fname = strchr(p + 1, '/');
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
846 if (!fname || c < fname) {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
847 fname = p + 1;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
848 av_strlcpy(rt->app, path + 1, p - path);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
849 } else {
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
850 fname++;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
851 av_strlcpy(rt->app, path + 1, fname - path - 1);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
852 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
853 }
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
854 }
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
855 if (!strchr(fname, ':') &&
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
856 (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
857 !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
858 memcpy(rt->playpath, "mp4:", 5);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
859 } else {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
860 rt->playpath[0] = 0;
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
861 }
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
862 strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
863
5668
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
864 rt->client_report_size = 1048576;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
865 rt->bytes_read = 0;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
866 rt->last_bytes_read = 0;
b13205b415b4 Make RTMP client send bytes read report
kostya
parents: 5606
diff changeset
867
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
868 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
869 proto, path, rt->app, rt->playpath);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
870 gen_connect(s, rt, proto, hostname, port);
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
871
5417
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
872 do {
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
873 ret = get_packet(s, 1);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
874 } while (ret == EAGAIN);
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
875 if (ret < 0)
9d7de5529047 cosmetics: reindent after last commit
kostya
parents: 5416
diff changeset
876 goto fail;
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
877
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
878 if (rt->is_input) {
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
879 // generate FLV header for demuxer
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
880 rt->flv_size = 13;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
881 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
882 rt->flv_off = 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
883 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
884 } else {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
885 rt->flv_size = 0;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
886 rt->flv_data = NULL;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
887 rt->flv_off = 0;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
888 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
889
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
890 s->max_packet_size = url_get_max_packet_size(rt->stream);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
891 s->is_streamed = 1;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
892 return 0;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
893
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
894 fail:
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
895 rtmp_close(s);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
896 return AVERROR(EIO);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
897 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
898
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
899 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
900 {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
901 RTMPContext *rt = s->priv_data;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
902 int orig_size = size;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
903 int ret;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
904
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
905 while (size > 0) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
906 int data_left = rt->flv_size - rt->flv_off;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
907
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
908 if (data_left >= size) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
909 memcpy(buf, rt->flv_data + rt->flv_off, size);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
910 rt->flv_off += size;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
911 return orig_size;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
912 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
913 if (data_left > 0) {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
914 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
915 buf += data_left;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
916 size -= data_left;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
917 rt->flv_off = rt->flv_size;
6142
bd851edc58ac RTMP: Return from rtmp_read as soon as some data is available
mstorsjo
parents: 6068
diff changeset
918 return data_left;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
919 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
920 if ((ret = get_packet(s, 0)) < 0)
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
921 return ret;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
922 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
923 return orig_size;
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
924 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
925
6068
7fdda2416684 Declare the url_write buffer parameter as const
mstorsjo
parents: 6055
diff changeset
926 static int rtmp_write(URLContext *h, const uint8_t *buf, int size)
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
927 {
5416
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
928 RTMPContext *rt = h->priv_data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
929 int size_temp = size;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
930 int pktsize, pkttype;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
931 uint32_t ts;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
932 const uint8_t *buf_temp = buf;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
933
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
934 if (size < 11) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
935 av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FLV packet too small %d\n", size);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
936 return 0;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
937 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
938
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
939 do {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
940 if (!rt->flv_off) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
941 //skip flv header
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
942 if (buf_temp[0] == 'F' && buf_temp[1] == 'L' && buf_temp[2] == 'V') {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
943 buf_temp += 9 + 4;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
944 size_temp -= 9 + 4;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
945 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
946
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
947 pkttype = bytestream_get_byte(&buf_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
948 pktsize = bytestream_get_be24(&buf_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
949 ts = bytestream_get_be24(&buf_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
950 ts |= bytestream_get_byte(&buf_temp) << 24;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
951 bytestream_get_be24(&buf_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
952 size_temp -= 11;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
953 rt->flv_size = pktsize;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
954
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
955 //force 12bytes header
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
956 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
957 pkttype == RTMP_PT_NOTIFY) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
958 if (pkttype == RTMP_PT_NOTIFY)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
959 pktsize += 16;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
960 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
961 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
962
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
963 //this can be a big packet, it's better to send it right here
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
964 ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
965 rt->out_pkt.extra = rt->main_channel_id;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
966 rt->flv_data = rt->out_pkt.data;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
967
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
968 if (pkttype == RTMP_PT_NOTIFY)
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
969 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
970 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
971
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
972 if (rt->flv_size - rt->flv_off > size_temp) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
973 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
974 rt->flv_off += size_temp;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
975 } else {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
976 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
977 rt->flv_off += rt->flv_size - rt->flv_off;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
978 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
979
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
980 if (rt->flv_off == rt->flv_size) {
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
981 bytestream_get_be32(&buf_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
982
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
983 ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
984 ff_rtmp_packet_destroy(&rt->out_pkt);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
985 rt->flv_size = 0;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
986 rt->flv_off = 0;
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
987 }
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
988 } while (buf_temp - buf < size_temp);
e01b6917b3cf Implement RTMP output (publishing FLV stream to RTMP server).
kostya
parents: 5414
diff changeset
989 return size;
5123
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
990 }
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
991
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
992 URLProtocol rtmp_protocol = {
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
993 "rtmp",
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
994 rtmp_open,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
995 rtmp_read,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
996 rtmp_write,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
997 NULL, /* seek */
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
998 rtmp_close,
cc34279f0fab RTMP protocol support (as a client)
kostya
parents:
diff changeset
999 };