[FFmpeg-soc] [soc]: r4460 - rtmp/rtmpdec.c
kostya
subversion at mplayerhq.hu
Tue Jun 16 18:48:34 CEST 2009
Author: kostya
Date: Tue Jun 16 18:48:34 2009
New Revision: 4460
Log:
Split URL into parts needed for connection parameters and update generating
of 'connect', 'createStream' and 'play' calls to RTMP server.
Modified:
rtmp/rtmpdec.c
Modified: rtmp/rtmpdec.c
==============================================================================
--- rtmp/rtmpdec.c Tue Jun 16 18:34:19 2009 (r4459)
+++ rtmp/rtmpdec.c Tue Jun 16 18:48:34 2009 (r4460)
@@ -39,41 +39,57 @@
typedef struct RTMPState {
URLContext *rtmp_hd;
RTMPPacketHistory rhist, whist;
+ char playpath[256];
} RTMPState;
-static void gen_connect(AVFormatContext *s, RTMPState *rt, const char *name)
+static void gen_connect(AVFormatContext *s, RTMPState *rt, const char *proto,
+ const char *host, int port, const char *app)
{
- uint8_t buf[65536], *p = buf;
+ RTMPPacket pkt;
+ uint8_t ver[32], *p;
+ char tcurl[512];
double num = 1.0;
- int size;
+ uint8_t bool;
- bytestream_put_byte(&p, 0x3);
- bytestream_put_be24(&p, 1);
- bytestream_put_be24(&p, 0);
- bytestream_put_byte(&p, RTMP_PT_INVOKE);
- bytestream_put_le32(&p, 0);
+ rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
+ p = pkt.data;
+ snprintf(tcurl, sizeof(tcurl), "%s://%s:%d/%s", proto, host, port, app);
rtmp_amf_write_tag(&p, AMF_STRING, "connect");
rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
rtmp_amf_write_tag(&p, AMF_OBJECT, NULL);
- rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "tcUrl");
- rtmp_amf_write_tag(&p, AMF_STRING, name);
rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "app");
- rtmp_amf_write_tag(&p, AMF_STRING, "app");
+ rtmp_amf_write_tag(&p, AMF_STRING, app);
+
+ snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
+ RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "flashVer");
- rtmp_amf_write_tag(&p, AMF_STRING, "LNX 6,0,82,0");
- rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "playpath");
- rtmp_amf_write_tag(&p, AMF_STRING, "1.mp4");
+ rtmp_amf_write_tag(&p, AMF_STRING, ver);
+ rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "tcUrl");
+ rtmp_amf_write_tag(&p, AMF_STRING, tcurl);
+ bool = 0;
+ rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "fpad");
+ rtmp_amf_write_tag(&p, AMF_NUMBER, &bool);
+ num = 15.0;
+ rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "capabilities");
+ rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
+ num = 1639.0;
+ rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "audioCodecs");
+ rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
+ num = 252.0;
+ rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "videoCodecs");
+ rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
+ num = 1.0;
+ rtmp_amf_write_tag(&p, AMF_STRING_IN_OBJECT, "videoFunction");
+ rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
rtmp_amf_write_tag(&p, AMF_OBJECT_END, NULL);
- size = p - buf;
- p = buf + 4;
- bytestream_put_be24(&p, size - 12);
+ pkt.data_size = p - pkt.data;
- url_write(rt->rtmp_hd, buf, size);
+ rtmp_packet_write(s, rt->rtmp_hd, &pkt, &rt->whist);
}
-static void gen_play(AVFormatContext *s, RTMPState *rt)
+static void gen_create_stream(AVFormatContext *s, RTMPState *rt)
{
RTMPPacket pkt;
uint8_t *p;
@@ -89,14 +105,36 @@ static void gen_play(AVFormatContext *s,
rtmp_packet_write(s, rt->rtmp_hd, &pkt, &rt->whist);
rtmp_packet_destroy(&pkt);
+}
- rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0, 17);
+static void gen_play(AVFormatContext *s, RTMPState *rt)
+{
+ RTMPPacket pkt;
+ uint8_t *p;
+ double num;
+
+ rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
+ 29 + strlen(rt->playpath));
num = 0.0;
p = pkt.data;
rtmp_amf_write_tag(&p, AMF_STRING, "play");
rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
rtmp_amf_write_tag(&p, AMF_NULL, NULL);
+ rtmp_amf_write_tag(&p, AMF_STRING, rt->playpath);
+ num = 0.0;
+ rtmp_amf_write_tag(&p, AMF_NUMBER, &num);
+
+ rtmp_packet_write(s, rt->rtmp_hd, &pkt, &rt->whist);
+ rtmp_packet_destroy(&pkt);
+
+ // set client buffer time disguised in ping packet
+ rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
+
+ p = pkt.data;
+ bytestream_put_be16(&p, 3);
+ bytestream_put_be32(&p, 1);
+ bytestream_put_be32(&p, 256); //TODO: what is a good value here?
rtmp_packet_write(s, rt->rtmp_hd, &pkt, &rt->whist);
rtmp_packet_destroy(&pkt);
@@ -151,13 +189,13 @@ static int rtmp_read_header(AVFormatCont
AVFormatParameters *ap)
{
RTMPState *rt = s->priv_data;
- char hostname[256];
+ char proto[8], hostname[256], path[512], app[128], *fname;
int port;
- uint8_t buf[65536];
+ uint8_t buf[2048];
AVStream *st;
- url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
- NULL, 0, s->filename);
+ url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
+ path, sizeof(path), s->filename);
rtmp_init_hist(&rt->rhist);
rtmp_init_hist(&rt->whist);
@@ -167,8 +205,39 @@ static int rtmp_read_header(AVFormatCont
url_open(&rt->rtmp_hd, buf, URL_RDWR);
if (rtmp_handshake(s, rt))
return -1;
- gen_connect(s, rt, s->filename);
- gen_play(s, rt);
+
+ //extract "app" part from path
+ if (!strncmp(path, "/ondemand/", 10)) {
+ fname = path + 10;
+ memcpy(app, "ondemand", 9);
+ } else {
+ char *p = strchr(path + 1, '/');
+ if (!p) {
+ fname = path + 1;
+ app[0] = '\0';
+ } else {
+ fname = strchr(p + 1, '/');
+ if (!fname) {
+ fname = p + 1;
+ strncpy(app, path + 1, p - path - 1);
+ } else {
+ fname++;
+ strncpy(app, path + 1, fname - path - 2);
+ }
+ }
+ }
+ if (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
+ !strcmp(fname + strlen(fname) - 4, ".mp4")) {
+ memcpy(rt->playpath, "mp4:", 5);
+ } else {
+ rt->playpath[0] = ':';
+ rt->playpath[0] = 0;
+ }
+ strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
+
+ av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
+ proto, path, app, rt->playpath);
+ gen_connect(s, rt, proto, hostname, port, app);
st = av_new_stream(s, 0);
if (!st)
More information about the FFmpeg-soc
mailing list