aboutsummaryrefslogtreecommitdiff
path: root/amf.cpp
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-12-20 05:09:26 +0800
committerMistivia <i@mistivia.com>2025-12-20 05:25:07 +0800
commit038c58b0ac053dbfe8aea3faab73863000d5fdc9 (patch)
tree5a7e477a5f75d76be7adc9dcaab82347bac82ae7 /amf.cpp
parentbb725cc3802b42992666e18d0758459e4332cdd7 (diff)
use srt instead of rtmp
Diffstat (limited to 'amf.cpp')
-rw-r--r--amf.cpp429
1 files changed, 0 insertions, 429 deletions
diff --git a/amf.cpp b/amf.cpp
deleted file mode 100644
index 2794419..0000000
--- a/amf.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-#include "amf.h"
-#include "rtmputils.h"
-
-#include <stdexcept>
-#include <string.h>
-#include <arpa/inet.h>
-
-namespace {
-
-uint8_t peek(const Decoder *dec)
-{
- if (dec->pos >= dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- return uint8_t(dec->buf[dec->pos]);
-}
-
-uint8_t get_byte(Decoder *dec)
-{
- if (dec->version == 0 && peek(dec) == AMF0_SWITCH_AMF3) {
- debug("entering AMF3 mode\n");
- dec->pos++;
- dec->version = 3;
- }
-
- if (dec->pos >= dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- return uint8_t(dec->buf[dec->pos++]);
-}
-
-}
-
-AMFValue::AMFValue(AMFType type) :
- m_type(type)
-{
- switch (m_type) {
- case AMF_OBJECT:
- case AMF_ECMA_ARRAY:
- m_value.object = new amf_object_t;
- break;
- case AMF_NUMBER:
- case AMF_INTEGER:
- case AMF_NULL:
- case AMF_UNDEFINED:
- break;
- default:
- assert(0);
- }
-}
-
-AMFValue::AMFValue(const std::string &s) :
- m_type(AMF_STRING)
-{
- m_value.string = new std::string(s);
-}
-
-AMFValue::AMFValue(double n) :
- m_type(AMF_NUMBER)
-{
- m_value.number = n;
-}
-
-AMFValue::AMFValue(int i) :
- m_type(AMF_INTEGER)
-{
- m_value.integer = i;
-}
-
-AMFValue::AMFValue(bool b) :
- m_type(AMF_BOOLEAN)
-{
- m_value.boolean = b;
-}
-
-AMFValue::AMFValue(const amf_object_t &object) :
- m_type(AMF_OBJECT)
-{
- m_value.object = new amf_object_t(object);
-}
-
-AMFValue::AMFValue(const AMFValue &from) :
- m_type(AMF_NULL)
-{
- *this = from;
-}
-
-AMFValue::~AMFValue()
-{
- destroy();
-}
-
-void AMFValue::destroy()
-{
- switch (m_type) {
- case AMF_STRING:
- delete m_value.string;
- break;
- case AMF_OBJECT:
- case AMF_ECMA_ARRAY:
- delete m_value.object;
- break;
- case AMF_NULL:
- case AMF_NUMBER:
- case AMF_INTEGER:
- case AMF_BOOLEAN:
- case AMF_UNDEFINED:
- break;
- }
-}
-
-void AMFValue::operator = (const AMFValue &from)
-{
- destroy();
- m_type = from.m_type;
- switch (m_type) {
- case AMF_STRING:
- m_value.string = new std::string(*from.m_value.string);
- break;
- case AMF_OBJECT:
- case AMF_ECMA_ARRAY:
- m_value.object = new amf_object_t(*from.m_value.object);
- break;
- case AMF_NUMBER:
- m_value.number = from.m_value.number;
- break;
- case AMF_INTEGER:
- m_value.integer = from.m_value.integer;
- break;
- case AMF_BOOLEAN:
- m_value.boolean = from.m_value.boolean;
- break;
- default:
- break;
- }
-}
-
-void amf_write(Encoder *enc, const std::string &s)
-{
- enc->buf += char(AMF0_STRING);
- uint16_t str_len = htons(s.size());
- enc->buf.append((char *) &str_len, 2);
- enc->buf += s;
-}
-
-void amf_write(Encoder *enc, int i)
-{
- throw std::runtime_error("AMF0 does not have integers");
-}
-
-void amf_write(Encoder *enc, double n)
-{
- enc->buf += char(AMF0_NUMBER);
- uint64_t encoded = 0;
-//#if defined(__i386__) || defined(__x86_64__)
- /* Flash uses same floating point format as x86 */
- memcpy(&encoded, &n, 8);
-//#endif
- uint32_t val = htonl(encoded >> 32);
- enc->buf.append((char *) &val, 4);
- val = htonl(encoded);
- enc->buf.append((char *) &val, 4);
-}
-
-void amf_write(Encoder *enc, bool b)
-{
- enc->buf += char(AMF0_BOOLEAN);
- enc->buf += char(b);
-}
-
-void amf_write_key(Encoder *enc, const std::string &s)
-{
- uint16_t str_len = htons(s.size());
- enc->buf.append((char *) &str_len, 2);
- enc->buf += s;
-}
-
-void amf_write(Encoder *enc, const amf_object_t &object)
-{
- enc->buf += char(AMF0_OBJECT);
- for (amf_object_t::const_iterator i = object.begin();
- i != object.end(); ++i) {
- amf_write_key(enc, i->first);
- amf_write(enc, i->second);
- }
- amf_write_key(enc, "");
- enc->buf += char(AMF0_OBJECT_END);
-}
-
-void amf_write_ecma(Encoder *enc, const amf_object_t &object)
-{
- enc->buf += char(AMF0_ECMA_ARRAY);
- uint32_t zero = 0;
- enc->buf.append((char *) &zero, 4);
- for (amf_object_t::const_iterator i = object.begin();
- i != object.end(); ++i) {
- amf_write_key(enc, i->first);
- amf_write(enc, i->second);
- }
- amf_write_key(enc, "");
- enc->buf += char(AMF0_OBJECT_END);
-}
-
-void amf_write_null(Encoder *enc)
-{
- enc->buf += char(AMF0_NULL);
-}
-
-void amf_write(Encoder *enc, const AMFValue &value)
-{
- switch (value.type()) {
- case AMF_STRING:
- amf_write(enc, value.as_string());
- break;
- case AMF_NUMBER:
- amf_write(enc, value.as_number());
- break;
- case AMF_INTEGER:
- amf_write(enc, value.as_integer());
- break;
- case AMF_BOOLEAN:
- amf_write(enc, value.as_boolean());
- break;
- case AMF_OBJECT:
- amf_write(enc, value.as_object());
- break;
- case AMF_ECMA_ARRAY:
- amf_write_ecma(enc, value.as_object());
- break;
- case AMF_NULL:
- amf_write_null(enc);
- break;
- default:
- break;
- }
-}
-
-unsigned int load_amf3_integer(Decoder *dec)
-{
- unsigned int value = 0;
- for (int i = 0; i < 4; ++i) {
- uint8_t b = get_byte(dec);
- if (i == 3) {
- /* use all bits from 4th byte */
- value = (value << 8) | b;
- break;
- }
- value = (value << 7) | (b & 0x7f);
- if ((b & 0x80) == 0)
- break;
- }
- return value;
-}
-
-std::string amf_load_string(Decoder *dec)
-{
- size_t str_len = 0;
- uint8_t type = get_byte(dec);
- if (dec->version == 3) {
- if (type != AMF3_STRING) {
- throw std::runtime_error("Expected a string");
- }
- str_len = load_amf3_integer(dec) / 2;
-
- } else {
- if (type != AMF0_STRING) {
- throw std::runtime_error("Expected a string");
- }
- if (dec->pos + 2 > dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- str_len = load_be16(&dec->buf[dec->pos]);
- dec->pos += 2;
- }
- if (dec->pos + str_len > dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- std::string s(dec->buf, dec->pos, str_len);
- dec->pos += str_len;
- return s;
-}
-
-double amf_load_number(Decoder *dec)
-{
- if (get_byte(dec) != AMF0_NUMBER) {
- throw std::runtime_error("Expected a string");
- }
- if (dec->pos + 8 > dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- uint64_t val = ((uint64_t) load_be32(&dec->buf[dec->pos]) << 32) |
- load_be32(&dec->buf[dec->pos + 4]);
- double n = 0;
-//#if defined(__i386__) || defined(__x86_64__)
- /* Flash uses same floating point format as x86 */
- memcpy(&n, &val, 8);
-//#endif
- dec->pos += 8;
- return n;
-}
-
-int amf_load_integer(Decoder *dec)
-{
- if (dec->version == 3) {
- return load_amf3_integer(dec);
- } else {
- return amf_load_number(dec);
- }
-}
-
-bool amf_load_boolean(Decoder *dec)
-{
- if (get_byte(dec) != AMF0_BOOLEAN) {
- throw std::runtime_error("Expected a boolean");
- }
- return get_byte(dec) != 0;
-}
-
-std::string amf_load_key(Decoder *dec)
-{
- if (dec->pos + 2 > dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- size_t str_len = load_be16(&dec->buf[dec->pos]);
- dec->pos += 2;
- if (dec->pos + str_len > dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- std::string s(dec->buf, dec->pos, str_len);
- dec->pos += str_len;
- return s;
-}
-
-amf_object_t amf_load_object(Decoder *dec)
-{
- amf_object_t object;
- if (get_byte(dec) != AMF0_OBJECT) {
- throw std::runtime_error("Expected an object");
- }
- while (1) {
- std::string key = amf_load_key(dec);
- if (key.empty())
- break;
- AMFValue value = amf_load(dec);
- object.insert(std::make_pair(key, value));
- }
- if (get_byte(dec) != AMF0_OBJECT_END) {
- throw std::runtime_error("expected object end");
- }
- return object;
-}
-
-amf_object_t amf_load_ecma(Decoder *dec)
-{
- /* ECMA array is the same as object, with 4 extra zero bytes */
- amf_object_t object;
- if (get_byte(dec) != AMF0_ECMA_ARRAY) {
- throw std::runtime_error("Expected an ECMA array");
- }
- if (dec->pos + 4 > dec->buf.size()) {
- throw std::runtime_error("Not enough data");
- }
- dec->pos += 4;
- while (1) {
- std::string key = amf_load_key(dec);
- if (key.empty())
- break;
- AMFValue value = amf_load(dec);
- object.insert(std::make_pair(key, value));
- }
- if (get_byte(dec) != AMF0_OBJECT_END) {
- throw std::runtime_error("expected object end");
- }
- return object;
-}
-
-AMFValue amf_load(Decoder *dec)
-{
- uint8_t type = peek(dec);
- if (dec->version == 3) {
- switch (type) {
- case AMF3_STRING:
- return AMFValue(amf_load_string(dec));
- case AMF3_NUMBER:
- return AMFValue(amf_load_number(dec));
- case AMF3_INTEGER:
- return AMFValue(amf_load_integer(dec));
- case AMF3_FALSE:
- dec->pos++;
- return AMFValue(false);
- case AMF3_TRUE:
- dec->pos++;
- return AMFValue(true);
- case AMF3_OBJECT:
- return AMFValue(amf_load_object(dec));
- case AMF3_ARRAY:
- return AMFValue(amf_load_ecma(dec));
- case AMF3_NULL:
- dec->pos++;
- return AMFValue(AMF_NULL);
- case AMF3_UNDEFINED:
- dec->pos++;
- return AMFValue(AMF_UNDEFINED);
- default:
- throw std::runtime_error(strf("Unsupported AMF3 type: %02x", type));
- }
- } else {
- switch (type) {
- case AMF0_STRING:
- return AMFValue(amf_load_string(dec));
- case AMF0_NUMBER:
- return AMFValue(amf_load_number(dec));
- case AMF0_BOOLEAN:
- return AMFValue(amf_load_boolean(dec));
- case AMF0_OBJECT:
- return AMFValue(amf_load_object(dec));
- case AMF0_ECMA_ARRAY:
- return AMFValue(amf_load_ecma(dec));
- case AMF0_NULL:
- dec->pos++;
- return AMFValue(AMF_NULL);
- case AMF0_UNDEFINED:
- dec->pos++;
- return AMFValue(AMF_UNDEFINED);
- default:
- throw std::runtime_error(strf("Unsupported AMF0 type: %02x", type));
- }
- }
-}