[FFmpeg-soc] [soc]: r4510 - in rtmp: rtmppkt.c rtmppkt.h rtmpproto.c
kostya
subversion at mplayerhq.hu
Wed Jun 24 09:30:29 CEST 2009
Author: kostya
Date: Wed Jun 24 09:30:29 2009
New Revision: 4510
Log:
Introduce AMF parsing functions and use them for parsing RTMP onStatus message
Modified:
rtmp/rtmppkt.c
rtmp/rtmppkt.h
rtmp/rtmpproto.c
Modified: rtmp/rtmppkt.c
==============================================================================
--- rtmp/rtmppkt.c Tue Jun 23 20:40:10 2009 (r4509)
+++ rtmp/rtmppkt.c Wed Jun 24 09:30:29 2009 (r4510)
@@ -193,6 +193,70 @@ void rtmp_packet_destroy(RTMPPacket *pkt
pkt->data_size = 0;
}
+int rtmp_amf_skip_data(const uint8_t *data)
+{
+ const uint8_t *base = data;
+
+ switch (*data++) {
+ case AMF_NUMBER: return 9;
+ case AMF_BOOLEAN: return 2;
+ case AMF_STRING: return 3 + AV_RB16(data);
+ case AMF_LONG_STRING: return 5 + AV_RB32(data);
+ case AMF_NULL: return 1;
+ case AMF_ECMA_ARRAY:
+ data += 4;
+ case AMF_OBJECT:
+ for (;;) {
+ int size = bytestream_get_be16(&data);
+ if (!size) {
+ data++;
+ break;
+ }
+ data += size;
+ data += rtmp_amf_skip_data(data);
+ }
+ return data - base;
+ case AMF_OBJECT_END: return 1;
+ default: return -1;
+ }
+}
+
+int rtmp_amf_find_field(const uint8_t *data, const uint8_t *name,
+ uint8_t *dst, int dst_size)
+{
+ int namelen = strlen(name);
+ int len;
+
+ if (*data++ != AMF_OBJECT)
+ return -1;
+ for (;;) {
+ int size = bytestream_get_be16(&data);
+ if (!size)
+ break;
+ data += size;
+ if (size == namelen && !memcmp(data-size, name, namelen)) {
+ switch (*data++) {
+ case AMF_NUMBER:
+ snprintf(dst, dst_size, "%g", av_int2dbl(AV_RB64(data)));
+ return 0;
+ case AMF_BOOLEAN:
+ snprintf(dst, dst_size, "%s", *data ? "true" : "false");
+ return 0;
+ case AMF_STRING:
+ len = bytestream_get_be16(&data);
+ av_strlcpy(dst, data, FFMIN(len+1, dst_size));
+ return 0;
+ default:
+ return -1;
+ }
+ }
+ len = rtmp_amf_skip_data(data);
+ if (len < 0)
+ return -1;
+ data += len;
+ }
+ return -1;
+}
static void parse_amf(const uint8_t *data, int size)
{
Modified: rtmp/rtmppkt.h
==============================================================================
--- rtmp/rtmppkt.h Tue Jun 23 20:40:10 2009 (r4509)
+++ rtmp/rtmppkt.h Wed Jun 24 09:30:29 2009 (r4510)
@@ -119,6 +119,11 @@ int rtmp_packet_write(URLContext *h, RTM
int rtmp_amf_tag_size(int type, const void *data);
+int rtmp_amf_skip_data(const uint8_t *data);
+
+int rtmp_amf_find_field(const uint8_t *data, const uint8_t *name,
+ uint8_t *dst, int dst_size);
+
void rtmp_amf_write_tag(uint8_t **dst, AMFType type, const void *data);
void rtmp_packet_inspect(RTMPPacket *pkt);
Modified: rtmp/rtmpproto.c
==============================================================================
--- rtmp/rtmpproto.c Tue Jun 23 20:40:10 2009 (r4509)
+++ rtmp/rtmpproto.c Wed Jun 24 09:30:29 2009 (r4510)
@@ -386,8 +386,23 @@ static int rtmp_parse_result(URLContext
break;
}
}
- if (!memcmp(pkt->data, "\002\000\008onStatus", 11)) {
- //TODO: catch stream close event
+ if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
+ const uint8_t* ptr = pkt->data + 11;
+ uint8_t tmpstr[256];
+ int t;
+
+ for (i = 0; i < 2; i++) {
+ t = rtmp_amf_skip_data(ptr);
+ if (t < 0)
+ return 1;
+ ptr += t;
+ }
+ t = rtmp_amf_find_field(ptr, "level", tmpstr, sizeof(tmpstr));
+ if (!t && !strcmp(tmpstr, "error")) {
+ if (!rtmp_amf_find_field(ptr, "description", tmpstr, sizeof(tmpstr)))
+ av_log(NULL/*s*/, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
+ return -1;
+ }
}
break;
}
More information about the FFmpeg-soc
mailing list