Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b
Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/rtmp/stream.c b/src/rtmp/stream.c
new file mode 100644
index 0000000..fe8748d
--- /dev/null
+++ b/src/rtmp/stream.c
@@ -0,0 +1,309 @@
+/**
+ * @file rtmp/stream.c Real Time Messaging Protocol (RTMP) -- NetStream
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include <re_net.h>
+#include <re_sa.h>
+#include <re_list.h>
+#include <re_tcp.h>
+#include <re_sys.h>
+#include <re_odict.h>
+#include <re_rtmp.h>
+#include "rtmp.h"
+
+
+static void destructor(void *data)
+{
+ struct rtmp_stream *strm = data;
+
+ list_unlink(&strm->le);
+
+ if (strm->created) {
+
+ rtmp_amf_command(strm->conn, 0, "deleteStream",
+ 3,
+ RTMP_AMF_TYPE_NUMBER, 0.0,
+ RTMP_AMF_TYPE_NULL,
+ RTMP_AMF_TYPE_NUMBER, (double)strm->stream_id);
+ }
+}
+
+
+/**
+ * Allocate a new RTMP Stream object
+ *
+ * @param strmp Pointer to allocated RTMP Stream
+ * @param conn RTMP Connection
+ * @param stream_id Stream id
+ * @param cmdh Command handler
+ * @param ctrlh Control handler
+ * @param auh Audio handler
+ * @param vidh Video handler
+ * @param datah Data handler
+ * @param arg Handler argument
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_stream_alloc(struct rtmp_stream **strmp, struct rtmp_conn *conn,
+ uint32_t stream_id, rtmp_command_h *cmdh,
+ rtmp_control_h *ctrlh, rtmp_audio_h *auh,
+ rtmp_video_h *vidh, rtmp_command_h *datah,
+ void *arg)
+{
+ struct rtmp_stream *strm;
+
+ if (!strmp || !conn)
+ return EINVAL;
+
+ strm = mem_zalloc(sizeof(*strm), destructor);
+ if (!strm)
+ return ENOMEM;
+
+ strm->conn = conn;
+ strm->stream_id = stream_id;
+
+ strm->cmdh = cmdh;
+ strm->ctrlh = ctrlh;
+ strm->auh = auh;
+ strm->vidh = vidh;
+ strm->datah = datah;
+ strm->arg = arg;
+
+ strm->chunk_id_audio = rtmp_conn_assign_chunkid(conn);
+ strm->chunk_id_video = rtmp_conn_assign_chunkid(conn);
+ strm->chunk_id_data = rtmp_conn_assign_chunkid(conn);
+
+ list_append(&conn->streaml, &strm->le, strm);
+
+ *strmp = strm;
+
+ return 0;
+}
+
+
+static void createstream_handler(bool success, const struct odict *msg,
+ void *arg)
+{
+ struct rtmp_stream *strm = arg;
+ uint64_t num;
+
+ if (!success)
+ goto out;
+
+ if (!odict_get_number(msg, &num, "3")) {
+ success = false;
+ goto out;
+ }
+
+ strm->stream_id = (uint32_t)num;
+ if (strm->stream_id == 0) {
+ success = false;
+ goto out;
+ }
+
+ strm->created = true;
+
+ out:
+ if (strm->resph)
+ strm->resph(success, msg, strm->arg);
+}
+
+
+/**
+ * Create a new RTMP Stream by sending "createStream" to the RTMP Server.
+ *
+ * @param strmp Pointer to allocated RTMP Stream
+ * @param conn RTMP Connection
+ * @param resph RTMP Response handler
+ * @param cmdh Command handler
+ * @param ctrlh Control handler
+ * @param auh Audio handler
+ * @param vidh Video handler
+ * @param datah Data handler
+ * @param arg Handler argument
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_stream_create(struct rtmp_stream **strmp, struct rtmp_conn *conn,
+ rtmp_resp_h *resph, rtmp_command_h *cmdh,
+ rtmp_control_h *ctrlh, rtmp_audio_h *auh,
+ rtmp_video_h *vidh, rtmp_command_h *datah,
+ void *arg)
+{
+ struct rtmp_stream *strm;
+ int err;
+
+ if (!strmp || !conn)
+ return EINVAL;
+
+ err = rtmp_stream_alloc(&strm, conn, (uint32_t)-1,
+ cmdh, ctrlh, auh, vidh, datah, arg);
+ if (err)
+ return err;
+
+ strm->resph = resph;
+
+ err = rtmp_amf_request(conn, 0,
+ "createStream", createstream_handler, strm,
+ 1,
+ RTMP_AMF_TYPE_NULL);
+ if (err)
+ goto out;
+
+ out:
+ if (err)
+ mem_deref(strm);
+ else
+ *strmp = strm;
+
+ return err;
+}
+
+
+/**
+ * Start playing an RTMP Stream by sending "play" to the RTMP Server
+ *
+ * @param strm RTMP Stream
+ * @param name Stream name
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_play(struct rtmp_stream *strm, const char *name)
+{
+ if (!strm || !name)
+ return EINVAL;
+
+ return rtmp_amf_command(strm->conn, strm->stream_id, "play",
+ 4,
+ RTMP_AMF_TYPE_NUMBER, 0.0,
+ RTMP_AMF_TYPE_NULL,
+ RTMP_AMF_TYPE_STRING, name,
+ RTMP_AMF_TYPE_NUMBER, -2000.0);
+}
+
+
+/**
+ * Start publishing an RTMP Stream by sending "publish" to the RTMP Server
+ *
+ * @param strm RTMP Stream
+ * @param name Stream name
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_publish(struct rtmp_stream *strm, const char *name)
+{
+ if (!strm || !name)
+ return EINVAL;
+
+ return rtmp_amf_command(strm->conn, strm->stream_id, "publish",
+ 4,
+ RTMP_AMF_TYPE_NUMBER, 0.0,
+ RTMP_AMF_TYPE_NULL,
+ RTMP_AMF_TYPE_STRING, name,
+ RTMP_AMF_TYPE_STRING, "live");
+}
+
+
+/**
+ * Send metadata on the stream to the RTMP Server
+ *
+ * @param strm RTMP Stream
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_meta(struct rtmp_stream *strm)
+{
+ if (!strm)
+ return EINVAL;
+
+ return rtmp_amf_data(strm->conn, strm->stream_id, "@setDataFrame",
+ 2,
+ RTMP_AMF_TYPE_STRING, "onMetaData",
+ RTMP_AMF_TYPE_ECMA_ARRAY, 2,
+ RTMP_AMF_TYPE_NUMBER, "audiocodecid", 10.0,
+ RTMP_AMF_TYPE_NUMBER, "videocodecid", 7.0);
+}
+
+
+/**
+ * Send audio packet on the RTMP Stream
+ *
+ * @param strm RTMP Stream
+ * @param timestamp Timestamp in [milliseconds]
+ * @param pld Audio payload
+ * @param len Payload length
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_send_audio(struct rtmp_stream *strm, uint32_t timestamp,
+ const uint8_t *pld, size_t len)
+{
+ uint32_t chunk_id;
+
+ if (!strm || !pld || !len)
+ return EINVAL;
+
+ chunk_id = strm->chunk_id_audio;
+
+ return rtmp_conn_send_msg(strm->conn, 0, chunk_id, timestamp, 0,
+ RTMP_TYPE_AUDIO, strm->stream_id, pld, len);
+}
+
+
+/**
+ * Send video packet on the RTMP Stream
+ *
+ * @param strm RTMP Stream
+ * @param timestamp Timestamp in [milliseconds]
+ * @param pld Video payload
+ * @param len Payload length
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtmp_send_video(struct rtmp_stream *strm, uint32_t timestamp,
+ const uint8_t *pld, size_t len)
+{
+ uint32_t chunk_id;
+
+ if (!strm || !pld || !len)
+ return EINVAL;
+
+ chunk_id = strm->chunk_id_video;
+
+ return rtmp_conn_send_msg(strm->conn, 0, chunk_id, timestamp, 0,
+ RTMP_TYPE_VIDEO, strm->stream_id, pld, len);
+}
+
+
+/**
+ * Find an RTMP Stream by stream id
+ *
+ * @param conn RTMP Connection
+ * @param stream_id Stream id
+ *
+ * @return RTMP Stream if found, or NULL if not found
+ */
+struct rtmp_stream *rtmp_stream_find(const struct rtmp_conn *conn,
+ uint32_t stream_id)
+{
+ struct le *le;
+
+ if (!conn)
+ return NULL;
+
+ for (le = list_head(&conn->streaml); le; le = le->next) {
+
+ struct rtmp_stream *strm = le->data;
+
+ if (stream_id == strm->stream_id)
+ return strm;
+ }
+
+ return NULL;
+}