]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtmppkt.c
win32: Use 64-bit fstat/lseek variants for MSVC as well
[ffmpeg] / libavformat / rtmppkt.c
index ed8e6b203d4b079a243d00f26807c5f032cf3571..119cdfa765e7e744d2e9b1afcd9a368ddbf2f35c 100644 (file)
@@ -47,6 +47,19 @@ void ff_amf_write_string(uint8_t **dst, const char *str)
     bytestream_put_buffer(dst, str, strlen(str));
 }
 
+void ff_amf_write_string2(uint8_t **dst, const char *str1, const char *str2)
+{
+    int len1 = 0, len2 = 0;
+    if (str1)
+        len1 = strlen(str1);
+    if (str2)
+        len2 = strlen(str2);
+    bytestream_put_byte(dst, AMF_DATA_TYPE_STRING);
+    bytestream_put_be16(dst, len1 + len2);
+    bytestream_put_buffer(dst, str1, len1);
+    bytestream_put_buffer(dst, str2, len2);
+}
+
 void ff_amf_write_null(uint8_t **dst)
 {
     bytestream_put_byte(dst, AMF_DATA_TYPE_NULL);
@@ -71,18 +84,73 @@ void ff_amf_write_object_end(uint8_t **dst)
     bytestream_put_be24(dst, AMF_DATA_TYPE_OBJECT_END);
 }
 
+int ff_amf_read_bool(GetByteContext *bc, int *val)
+{
+    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_BOOL)
+        return AVERROR_INVALIDDATA;
+    *val = bytestream2_get_byte(bc);
+    return 0;
+}
+
+int ff_amf_read_number(GetByteContext *bc, double *val)
+{
+    uint64_t read;
+    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NUMBER)
+        return AVERROR_INVALIDDATA;
+    read = bytestream2_get_be64(bc);
+    *val = av_int2double(read);
+    return 0;
+}
+
+int ff_amf_read_string(GetByteContext *bc, uint8_t *str,
+                       int strsize, int *length)
+{
+    int stringlen = 0;
+    int readsize;
+    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_STRING)
+        return AVERROR_INVALIDDATA;
+    stringlen = bytestream2_get_be16(bc);
+    if (stringlen + 1 > strsize)
+        return AVERROR(EINVAL);
+    readsize = bytestream2_get_buffer(bc, str, stringlen);
+    if (readsize != stringlen) {
+        av_log(NULL, AV_LOG_WARNING,
+               "Unable to read as many bytes as AMF string signaled\n");
+    }
+    str[readsize] = '\0';
+    *length = FFMIN(stringlen, readsize);
+    return 0;
+}
+
+int ff_amf_read_null(GetByteContext *bc)
+{
+    if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_NULL)
+        return AVERROR_INVALIDDATA;
+    return 0;
+}
+
 int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
                         int chunk_size, RTMPPacket *prev_pkt)
 {
-    uint8_t hdr, t, buf[16];
+    uint8_t hdr;
+
+    if (ffurl_read(h, &hdr, 1) != 1)
+        return AVERROR(EIO);
+
+    return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt, hdr);
+}
+
+int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
+                                 RTMPPacket *prev_pkt, uint8_t hdr)
+{
+
+    uint8_t t, buf[16];
     int channel_id, timestamp, data_size, offset = 0;
     uint32_t extra = 0;
     enum RTMPPacketType type;
     int size = 0;
     int ret;
 
-    if (ffurl_read(h, &hdr, 1) != 1)
-        return AVERROR(EIO);
     size++;
     channel_id = hdr & 0x3F;
 
@@ -288,11 +356,11 @@ int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
                 data++;
                 break;
             }
-            if (data + size >= data_end || data + size < data)
+            if (size < 0 || size >= data_end - data)
                 return -1;
             data += size;
             t = ff_amf_tag_size(data, data_end);
-            if (t < 0 || data + t >= data_end)
+            if (t < 0 || t >= data_end - data)
                 return -1;
             data += t;
         }
@@ -321,7 +389,7 @@ int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
         int size = bytestream_get_be16(&data);
         if (!size)
             break;
-        if (data + size >= data_end || data + size < data)
+        if (size < 0 || size >= data_end - data)
             return -1;
         data += size;
         if (size == namelen && !memcmp(data-size, name, namelen)) {
@@ -342,7 +410,7 @@ int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
             return 0;
         }
         len = ff_amf_tag_size(data, data_end);
-        if (len < 0 || data + len >= data_end || data + len < data)
+        if (len < 0 || len >= data_end - data)
             return -1;
         data += len;
     }
@@ -372,7 +440,7 @@ static const char* rtmp_packet_type(int type)
 
 static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end)
 {
-    int size;
+    unsigned int size;
     char buf[1024];
 
     if (data >= data_end)
@@ -391,7 +459,7 @@ static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *d
         } else {
             size = bytestream_get_be32(&data);
         }
-        size = FFMIN(size, 1023);
+        size = FFMIN(size, sizeof(buf) - 1);
         memcpy(buf, data, size);
         buf[size] = 0;
         av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
@@ -404,22 +472,21 @@ static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *d
     case AMF_DATA_TYPE_OBJECT:
         av_log(ctx, AV_LOG_DEBUG, " {\n");
         for (;;) {
-            int size = bytestream_get_be16(&data);
             int t;
-            memcpy(buf, data, size);
-            buf[size] = 0;
+            size = bytestream_get_be16(&data);
+            av_strlcpy(buf, data, FFMIN(sizeof(buf), size + 1));
             if (!size) {
                 av_log(ctx, AV_LOG_DEBUG, " }\n");
                 data++;
                 break;
             }
-            if (data + size >= data_end || data + size < data)
+            if (size >= data_end - data)
                 return;
             data += size;
             av_log(ctx, AV_LOG_DEBUG, "  %s: ", buf);
             ff_amf_tag_contents(ctx, data, data_end);
             t = ff_amf_tag_size(data, data_end);
-            if (t < 0 || data + t >= data_end)
+            if (t < 0 || t >= data_end - data)
                 return;
             data += t;
         }