281 lines
11 KiB
C++
281 lines
11 KiB
C++
#include "rtmp-netstream.h"
|
|
#include "rtmp-internal.h"
|
|
#include "amf0.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// @param[in] streamName flv:sample, mp3:sample, H.264/AAC: mp4:sample.m4v
|
|
// @param[in] start -2-live/vod, -1-live only, >=0-seek position
|
|
// @param[in] duration <=-1-all, 0-single frame, >0-period
|
|
// @param[in] reset 1-flush any previous playlist, 0-don't flush
|
|
uint8_t* rtmp_netstream_play(uint8_t* out, size_t bytes, double transactionId, const char* name, double start, double duration, int reset)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "play";
|
|
|
|
if (NULL == name)
|
|
return NULL;
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, name, strlen(name)); // Stream Name
|
|
out = AMFWriteDouble(out, end, start); // Start Number
|
|
out = AMFWriteDouble(out, end, duration); // Duration Number
|
|
out = AMFWriteBoolean(out, end, (uint8_t)reset); // Reset Boolean
|
|
return out;
|
|
}
|
|
|
|
// reponse: none
|
|
uint8_t* rtmp_netstream_delete_stream(uint8_t* out, size_t bytes, double transactionId, double streamId)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "deleteStream";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteDouble(out, end, streamId); // Stream ID
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netconnection_close_stream(uint8_t* out, size_t bytes, double transactionId, double streamId)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "closeStream";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command));
|
|
out = AMFWriteDouble(out, end, transactionId);
|
|
out = AMFWriteNull(out, end);
|
|
out = AMFWriteDouble(out, end, streamId);
|
|
return out;
|
|
}
|
|
|
|
// reponse: enable-false: none, enable-true: onStatus with NetStream.Seek.Notify/NetStream.Play.Start
|
|
uint8_t* rtmp_netstream_receive_audio(uint8_t* out, size_t bytes, double transactionId, int enable)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "receiveAudio";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteBoolean(out, end, (uint8_t)enable); // Bool Flag
|
|
return out;
|
|
}
|
|
|
|
// reponse: enable-false: none, enable-true: onStatus with NetStream.Seek.Notify/NetStream.Play.Start
|
|
uint8_t* rtmp_netstream_receive_video(uint8_t* out, size_t bytes, double transactionId, int enable)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "receiveVideo";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteBoolean(out, end, (uint8_t)enable); // Bool Flag
|
|
return out;
|
|
}
|
|
|
|
// response: onStatus beginning of publish
|
|
uint8_t* rtmp_netstream_publish(uint8_t* out, size_t bytes, double transactionId, const char* stream_name, const char* stream_type)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "publish";
|
|
|
|
if (NULL == stream_name || NULL == stream_type)
|
|
return NULL;
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, stream_name, strlen(stream_name)); // Publishing Name
|
|
out = AMFWriteString(out, end, stream_type, strlen(stream_type)); // Publishing Type
|
|
return out;
|
|
}
|
|
|
|
// response: success: onStatus-NetStream.Seek.Notify, failure: _error message
|
|
uint8_t* rtmp_netstream_seek(uint8_t* out, size_t bytes, double transactionId, double ms)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "seek";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteDouble(out, end, ms); // milliSeconds Number
|
|
return out;
|
|
}
|
|
|
|
// @param[in] pause 1-pausing, 0-resuing
|
|
// response: success: onStatus-NetStream.Pause.Notify/NetStream.Unpause.Notify, failure: _error message
|
|
uint8_t* rtmp_netstream_pause(uint8_t* out, size_t bytes, double transactionId, int pause, double ms)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "pause";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteBoolean(out, end, (uint8_t)pause); // pause/unpause
|
|
out = AMFWriteDouble(out, end, ms); // milliSeconds Number
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_release_stream(uint8_t* out, size_t bytes, double transactionId, const char* stream_name)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "releaseStream";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, stream_name, strlen(stream_name)); // playpath
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_fcpublish(uint8_t* out, size_t bytes, double transactionId, const char* stream_name)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "FCPublish";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, stream_name, strlen(stream_name)); // playpath
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_fcunpublish(uint8_t* out, size_t bytes, double transactionId, const char* stream_name)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "FCUnpublish";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, stream_name, strlen(stream_name)); // playpath
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_fcsubscribe(uint8_t* out, size_t bytes, double transactionId, const char* subscribepath)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "FCSubscribe";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, subscribepath, strlen(subscribepath)); // subscribepath
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_fcunsubscribe(uint8_t* out, size_t bytes, double transactionId, const char* subscribepath)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "FCUnsubscribe";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
out = AMFWriteString(out, end, subscribepath, strlen(subscribepath)); // subscribepath
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_onbwdone(uint8_t* out, size_t bytes, double transactionId, double bandwidth)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "onBWDone";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command));
|
|
out = AMFWriteDouble(out, end, transactionId);
|
|
out = AMFWriteNull(out, end);
|
|
out = AMFWriteDouble(out, end, bandwidth);
|
|
return out;
|
|
}
|
|
|
|
// c -> s
|
|
uint8_t* rtmp_netstream_checkbw(uint8_t* out, size_t bytes, double transactionId)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "_checkbw";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_onstatus(uint8_t* out, size_t bytes, double transactionId, const char* level, const char* code, const char* description)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "onStatus";
|
|
|
|
if (NULL == level || NULL == code || NULL == description)
|
|
return NULL;
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
|
|
out = AMFWriteObject(out, end);
|
|
out = AMFWriteNamedString(out, end, "level", 5, level, strlen(level));
|
|
out = AMFWriteNamedString(out, end, "code", 4, code, strlen(code));
|
|
out = AMFWriteNamedString(out, end, "description", 11, description, strlen(description));
|
|
out = AMFWriteObjectEnd(out, end);
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_onreconnect(uint8_t* out, size_t bytes, double transactionId, const char* tcurl, const char* description)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "onStatus";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
|
|
out = AMFWriteObject(out, end);
|
|
out = AMFWriteNamedString(out, end, "level", 5, RTMP_LEVEL_STATUS, strlen(RTMP_LEVEL_STATUS));
|
|
out = AMFWriteNamedString(out, end, "code", 4, "NetConnection.Connect.ReconnectRequest", 39);
|
|
out = AMFWriteNamedString(out, end, "description", 11, description?description:"", strlen(description ? description : ""));
|
|
out = AMFWriteNamedString(out, end, "tcUrl", 5, tcurl?tcurl:"", strlen(tcurl ? tcurl : ""));
|
|
out = AMFWriteObjectEnd(out, end);
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_onconnect_rejected(uint8_t* out, size_t bytes, double transactionId, const char* tcurl, const char* description)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "_error";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteDouble(out, end, transactionId); // Transaction ID
|
|
out = AMFWriteNull(out, end); // command object
|
|
|
|
out = AMFWriteObject(out, end);
|
|
out = AMFWriteNamedString(out, end, "level", 5, RTMP_LEVEL_ERROR, strlen(RTMP_LEVEL_ERROR));
|
|
out = AMFWriteNamedString(out, end, "code", 4, "NetConnection.Connect.Rejected", 31);
|
|
out = AMFWriteNamedString(out, end, "description", 11, description ? description : "", strlen(description ? description : ""));
|
|
|
|
out = AMFWriteNamed(out, end, "ex", 2);
|
|
out = AMFWriteObject(out, end);
|
|
out = AMFWriteNamedDouble(out, end, "code", 4, 302);
|
|
out = AMFWriteNamedString(out, end, "redirect", 8, tcurl ? tcurl : "", strlen(tcurl ? tcurl : ""));
|
|
out = AMFWriteObjectEnd(out, end);
|
|
|
|
out = AMFWriteObjectEnd(out, end);
|
|
return out;
|
|
}
|
|
|
|
uint8_t* rtmp_netstream_rtmpsampleaccess(uint8_t* out, size_t bytes)
|
|
{
|
|
uint8_t* end = out + bytes;
|
|
const char* command = "|RtmpSampleAccess";
|
|
|
|
out = AMFWriteString(out, end, command, strlen(command)); // Command Name
|
|
out = AMFWriteBoolean(out, end, 1);
|
|
out = AMFWriteBoolean(out, end, 1);
|
|
return out;
|
|
}
|