[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