[rtmpdump] r356 - in trunk/librtmp: rtmp.c rtmp.h
hyc
subversion at mplayerhq.hu
Tue Mar 16 05:06:23 CET 2010
Author: hyc
Date: Tue Mar 16 05:06:22 2010
New Revision: 356
Log:
Partial RTMP_Write implementation
Modified:
trunk/librtmp/rtmp.c
trunk/librtmp/rtmp.h
Modified: trunk/librtmp/rtmp.c
==============================================================================
--- trunk/librtmp/rtmp.c Tue Mar 16 01:18:11 2010 (r355)
+++ trunk/librtmp/rtmp.c Tue Mar 16 05:06:22 2010 (r356)
@@ -275,9 +275,7 @@ RTMP_SetupStream(RTMP *r,
double dTime,
uint32_t dLength, bool bLiveStream, long int timeout)
{
- assert(protocol < 9);
-
- Log(LOGDEBUG, "Protocol : %s", RTMPProtocolStrings[protocol]);
+ Log(LOGDEBUG, "Protocol : %s", RTMPProtocolStrings[protocol&7]);
Log(LOGDEBUG, "Hostname : %s", hostname);
Log(LOGDEBUG, "Port : %d", port);
Log(LOGDEBUG, "Playpath : %s", playpath->av_val);
@@ -598,7 +596,7 @@ RTMP_ReconnectStream(RTMP *r, int buffer
{
RTMP_DeleteStream(r);
- RTMP_SendCreateStream(r, 2.0);
+ RTMP_SendCreateStream(r);
RTMP_SetBufferMS(r, bufferTime);
@@ -1009,6 +1007,8 @@ SAVC(videoFunction);
SAVC(objectEncoding);
SAVC(secureToken);
SAVC(secureTokenResponse);
+SAVC(type);
+SAVC(nonprivate);
static bool
SendConnectPacket(RTMP *r, RTMPPacket *cp)
@@ -1029,12 +1029,15 @@ SendConnectPacket(RTMP *r, RTMPPacket *c
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_connect);
- enc = AMF_EncodeNumber(enc, pend, 1.0);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_OBJECT;
- if (r->Link.app.av_len)
+ enc = AMF_EncodeNamedString(enc, pend, &av_app, &r->Link.app);
+ if (!enc)
+ return false;
+ if (r->Link.protocol & RTMP_FEATURE_WRITE)
{
- enc = AMF_EncodeNamedString(enc, pend, &av_app, &r->Link.app);
+ enc = AMF_EncodeNamedString(enc, pend, &av_type, &av_nonprivate);
if (!enc)
return false;
}
@@ -1056,30 +1059,33 @@ SendConnectPacket(RTMP *r, RTMPPacket *c
if (!enc)
return false;
}
- enc = AMF_EncodeNamedBoolean(enc, pend, &av_fpad, false);
- if (!enc)
- return false;
- enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0);
- if (!enc)
- return false;
- enc = AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, r->m_fAudioCodecs);
- if (!enc)
- return false;
- enc = AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, r->m_fVideoCodecs);
- if (!enc)
- return false;
- enc = AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0);
- if (!enc)
- return false;
- if (r->Link.pageUrl.av_len)
+ if (!(r->Link.protocol & RTMP_FEATURE_WRITE))
{
- enc = AMF_EncodeNamedString(enc, pend, &av_pageUrl, &r->Link.pageUrl);
+ enc = AMF_EncodeNamedBoolean(enc, pend, &av_fpad, false);
+ if (!enc)
+ return false;
+ enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0);
if (!enc)
return false;
+ enc = AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, r->m_fAudioCodecs);
+ if (!enc)
+ return false;
+ enc = AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, r->m_fVideoCodecs);
+ if (!enc)
+ return false;
+ enc = AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0);
+ if (!enc)
+ return false;
+ if (r->Link.pageUrl.av_len)
+ {
+ enc = AMF_EncodeNamedString(enc, pend, &av_pageUrl, &r->Link.pageUrl);
+ if (!enc)
+ return false;
+ }
}
if (r->m_fEncoding != 0.0 || r->m_bSendEncoding)
- {
- enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r->m_fEncoding); // AMF0, AMF3 not supported yet
+ { // AMF0, AMF3 not fully supported yet
+ enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r->m_fEncoding);
if (!enc)
return false;
}
@@ -1149,7 +1155,7 @@ SendBGHasStream(RTMP *r, double dId, AVa
SAVC(createStream);
bool
-RTMP_SendCreateStream(RTMP *r, double dCmdID)
+RTMP_SendCreateStream(RTMP *r)
{
RTMPPacket packet;
char pbuf[256], *pend = pbuf + sizeof(pbuf);
@@ -1164,7 +1170,7 @@ RTMP_SendCreateStream(RTMP *r, double dC
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_createStream);
- enc = AMF_EncodeNumber(enc, pend, dCmdID);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL; // NULL
packet.m_nBodySize = enc - packet.m_body;
@@ -1190,7 +1196,7 @@ SendFCSubscribe(RTMP *r, AVal *subscribe
Log(LOGDEBUG, "FCSubscribe: %s", subscribepath->av_val);
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_FCSubscribe);
- enc = AMF_EncodeNumber(enc, pend, 4.0);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL;
enc = AMF_EncodeString(enc, pend, subscribepath);
@@ -1202,6 +1208,98 @@ SendFCSubscribe(RTMP *r, AVal *subscribe
return RTMP_SendPacket(r, &packet, true);
}
+SAVC(releaseStream);
+
+static bool
+SendReleaseStream(RTMP *r)
+{
+ RTMPPacket packet;
+ char pbuf[1024], *pend = pbuf + sizeof(pbuf);
+
+ packet.m_nChannel = 0x03; // control channel (invoke)
+ packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
+ packet.m_packetType = 0x14; // INVOKE
+ packet.m_nInfoField1 = 0;
+ packet.m_nInfoField2 = 0;
+ packet.m_hasAbsTimestamp = 0;
+ packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
+
+ char *enc = packet.m_body;
+ enc = AMF_EncodeString(enc, pend, &av_releaseStream);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
+ *enc++ = AMF_NULL;
+ enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
+ if (!enc)
+ return false;
+
+ packet.m_nBodySize = enc - packet.m_body;
+
+ return RTMP_SendPacket(r, &packet, true);
+}
+
+SAVC(FCPublish);
+
+static bool
+SendFCPublish(RTMP *r)
+{
+ RTMPPacket packet;
+ char pbuf[1024], *pend = pbuf + sizeof(pbuf);
+
+ packet.m_nChannel = 0x03; // control channel (invoke)
+ packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
+ packet.m_packetType = 0x14; // INVOKE
+ packet.m_nInfoField1 = 0;
+ packet.m_nInfoField2 = 0;
+ packet.m_hasAbsTimestamp = 0;
+ packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
+
+ char *enc = packet.m_body;
+ enc = AMF_EncodeString(enc, pend, &av_FCPublish);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
+ *enc++ = AMF_NULL;
+ enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
+ if (!enc)
+ return false;
+
+ packet.m_nBodySize = enc - packet.m_body;
+
+ return RTMP_SendPacket(r, &packet, true);
+}
+
+SAVC(publish);
+SAVC(live);
+
+static bool
+SendPublish(RTMP *r)
+{
+ RTMPPacket packet;
+ char pbuf[1024], *pend = pbuf + sizeof(pbuf);
+
+ packet.m_nChannel = 0x04; // source channel (invoke)
+ packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
+ packet.m_packetType = 0x14; // INVOKE
+ packet.m_nInfoField1 = 0;
+ packet.m_nInfoField2 = 0;
+ packet.m_hasAbsTimestamp = 0;
+ packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
+
+ char *enc = packet.m_body;
+ enc = AMF_EncodeString(enc, pend, &av_publish);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
+ *enc++ = AMF_NULL;
+ enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
+ if (!enc)
+ return false;
+
+ enc = AMF_EncodeString(enc, pend, &av_live);
+ if (!enc)
+ return false;
+
+ packet.m_nBodySize = enc - packet.m_body;
+
+ return RTMP_SendPacket(r, &packet, true);
+}
+
SAVC(deleteStream);
static bool
@@ -1220,7 +1318,7 @@ SendDeleteStream(RTMP *r, double dStream
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_deleteStream);
- enc = AMF_EncodeNumber(enc, pend, 0.0);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL;
enc = AMF_EncodeNumber(enc, pend, dStreamId);
@@ -1248,7 +1346,7 @@ RTMP_SendPause(RTMP *r, bool DoPause, do
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_pause);
- enc = AMF_EncodeNumber(enc, pend, 0);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL;
enc = AMF_EncodeBoolean(enc, pend, DoPause);
enc = AMF_EncodeNumber(enc, pend, (double)dTime);
@@ -1277,7 +1375,7 @@ RTMP_SendSeek(RTMP *r, double dTime)
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_seek);
- enc = AMF_EncodeNumber(enc, pend, 0);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL;
enc = AMF_EncodeNumber(enc, pend, dTime);
@@ -1350,7 +1448,7 @@ SendCheckBW(RTMP *r)
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av__checkbw);
- enc = AMF_EncodeNumber(enc, pend, 0);
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL;
packet.m_nBodySize = enc - packet.m_body;
@@ -1404,7 +1502,7 @@ SendPlay(RTMP *r)
char *enc = packet.m_body;
enc = AMF_EncodeString(enc, pend, &av_play);
- enc = AMF_EncodeNumber(enc, pend, 0.0); // stream id??
+ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
*enc++ = AMF_NULL;
Log(LOGDEBUG, "%s, seekTime=%.2f, dLength=%d, sending play: %s",
@@ -1648,23 +1746,40 @@ HandleInvoke(RTMP *r, const char *body,
SendSecureTokenResponse(r, &p.p_vu.p_aval);
}
}
- RTMP_SendServerBW(r);
- RTMP_SendCtrl(r, 3, 0, 300);
-
- RTMP_SendCreateStream(r, 2.0);
+ if (r->Link.protocol & RTMP_FEATURE_WRITE)
+ {
+ SendReleaseStream(r);
+ SendFCPublish(r);
+ }
+ else
+ {
+ RTMP_SendServerBW(r);
+ RTMP_SendCtrl(r, 3, 0, 300);
+ }
+ RTMP_SendCreateStream(r);
- /* Send the FCSubscribe if live stream or if subscribepath is set */
- if (r->Link.subscribepath.av_len)
- SendFCSubscribe(r, &r->Link.subscribepath);
- else if (r->Link.bLiveStream)
- SendFCSubscribe(r, &r->Link.playpath);
+ if (!(r->Link.protocol & RTMP_FEATURE_WRITE))
+ {
+ /* Send the FCSubscribe if live stream or if subscribepath is set */
+ if (r->Link.subscribepath.av_len)
+ SendFCSubscribe(r, &r->Link.subscribepath);
+ else if (r->Link.bLiveStream)
+ SendFCSubscribe(r, &r->Link.playpath);
+ }
}
else if (AVMATCH(&methodInvoked, &av_createStream))
{
r->m_stream_id = (int)AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3));
- SendPlay(r);
- RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);
+ if (r->Link.protocol & RTMP_FEATURE_WRITE)
+ {
+ SendPublish(r);
+ }
+ else
+ {
+ SendPlay(r);
+ RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);
+ }
}
else if (AVMATCH(&methodInvoked, &av_play))
{
@@ -2614,6 +2729,7 @@ RTMP_Close(RTMP *r)
AV_clear(r->m_methodCalls, r->m_numCalls);
r->m_methodCalls = NULL;
r->m_numCalls = 0;
+ r->m_numInvokes = 0;
r->m_bPlaying = false;
r->m_sb.sb_size = 0;
@@ -3408,3 +3524,66 @@ RTMP_Read(RTMP *r, char *buf, int size)
total += size;
return total;
}
+
+static const AVal av_setDataFrame = AVC("@setDataFrame");
+
+int
+RTMP_Write(RTMP *r, char *buf, int size)
+{
+ RTMPPacket packet;
+ char *pend, *enc;
+ int s2 = size, ret;
+
+ if (size < 11) {
+ /* FLV pkt too small */
+ return 0;
+ }
+
+ packet.m_nChannel = 0x04; // source channel
+ packet.m_nInfoField2 = 0;
+
+ if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V')
+ {
+ buf += 13;
+ s2 -= 13;
+ }
+
+ packet.m_packetType = *buf++;
+ packet.m_nBodySize = AMF_DecodeInt24(buf);
+ buf += 3;
+ packet.m_nInfoField1 = AMF_DecodeInt24(buf);
+ buf += 3;
+ packet.m_nInfoField1 |= *buf++ << 24;
+ buf += 3;
+ s2 -= 11;
+
+ if (((packet.m_packetType == 0x08 || packet.m_packetType == 0x09) &&
+ !packet.m_nInfoField1) || packet.m_packetType == 0x12)
+ {
+ packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
+ packet.m_hasAbsTimestamp = 1;
+ if (packet.m_packetType == 0x12)
+ packet.m_nBodySize += 16;
+ }
+ else
+ {
+ packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
+ packet.m_hasAbsTimestamp = 0;
+ }
+
+ if (!RTMPPacket_Alloc(&packet, packet.m_nBodySize))
+ {
+ Log(LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__);
+ return false;
+ }
+ enc = packet.m_body;
+ pend = enc + packet.m_nBodySize;
+ if (packet.m_packetType == 0x12)
+ enc = AMF_EncodeString(enc, pend, &av_setDataFrame);
+ memcpy(enc, buf, packet.m_nBodySize);
+ ret = RTMP_SendPacket(r, &packet, false);
+ RTMPPacket_Free(&packet);
+ if (!ret)
+ return -1;
+ return size;
+}
Modified: trunk/librtmp/rtmp.h
==============================================================================
--- trunk/librtmp/rtmp.h Tue Mar 16 01:18:11 2010 (r355)
+++ trunk/librtmp/rtmp.h Tue Mar 16 05:06:22 2010 (r356)
@@ -39,7 +39,9 @@ extern "C"
#define RTMP_FEATURE_HTTP 0x01
#define RTMP_FEATURE_ENC 0x02
#define RTMP_FEATURE_SSL 0x04
-#define RTMP_FEATURE_MFP 0x08 // not yet supported
+#define RTMP_FEATURE_MFP 0x08 /* not yet supported */
+#define RTMP_FEATURE_WRITE 0x10 /* publish, not play */
+#define RTMP_FEATURE_HTTP2 0x20 /* server-side rtmpt */
#define RTMP_PROTOCOL_UNDEFINED -1
#define RTMP_PROTOCOL_RTMP 0
@@ -205,8 +207,9 @@ extern "C"
uint8_t m_bSendEncoding;
uint8_t m_bSendCounter;
- AVal *m_methodCalls; /* remote method calls queue */
+ int m_numInvokes;
int m_numCalls;
+ AVal *m_methodCalls; /* remote method calls queue */
RTMP_LNK Link;
RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS];
@@ -286,7 +289,7 @@ extern "C"
int RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int len);
int RTMPSockBuf_Close(RTMPSockBuf *sb);
- bool RTMP_SendCreateStream(RTMP *r, double dCmdID);
+ bool RTMP_SendCreateStream(RTMP *r);
bool RTMP_SendSeek(RTMP *r, double dTime);
bool RTMP_SendServerBW(RTMP *r);
void RTMP_DropRequest(RTMP *r, int i, bool freeit);
More information about the rtmpdump
mailing list