New upstream version 26.0.0+dfsg1

This commit is contained in:
Sebastian Ramacher 2020-10-01 22:15:25 +02:00
parent 8e020cdacb
commit 240080891f
837 changed files with 41275 additions and 9196 deletions

View file

@ -5,22 +5,21 @@ set_property(CACHE WITH_RTMPS PROPERTY STRINGS AUTO ON OFF)
option(STATIC_MBEDTLS "Statically link mbedTLS into binary" OFF)
if (WITH_RTMPS OR (WITH_RTMPS STREQUAL "AUTO"))
find_package(MbedTLS QUIET)
find_package(ZLIB QUIET)
if (WITH_RTMPS STREQUAL "AUTO")
find_package(MbedTLS)
find_package(ZLIB)
if (NOT MBEDTLS_FOUND OR NOT ZLIB_FOUND)
set(WITH_RTMPS "OFF")
message(WARNING "mbedTLS or zlib was not found, RTMPS will be auto-disabled")
endif()
endif()
if (LIBMBEDTLS_FOUND AND ZLIB_FOUND)
if (WITH_RTMPS)
find_package(MbedTLS REQUIRED)
find_package(ZLIB REQUIRED)
add_definitions(-DCRYPTO -DUSE_MBEDTLS)
include_directories(${LIBMBEDTLS_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
include_directories(${MBEDTLS_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
else()
if(WITH_RTMPS STREQUAL "AUTO")
message(WARNING "mbedTLS was not found, RTMPS will be auto-disabled")
elseif (WITH_RTMPS)
message(FATAL_ERROR "RTMPS enabled by user, but mbedTLS was not found")
endif()
unset(LIBMBEDTLS_LIBRARIES)
unset(ZLIB_LIBRARIES)
add_definitions(-DNO_CRYPTO)
endif()
@ -172,9 +171,10 @@ add_library(obs-outputs MODULE
${obs-outputs_librtmp_HEADERS})
target_link_libraries(obs-outputs
libobs
${LIBMBEDTLS_LIBRARIES}
${MBEDTLS_LIBRARIES}
${ZLIB_LIBRARIES}
${ftl_IMPORTS}
${obs-outputs_PLATFORM_DEPS})
set_target_properties(obs-outputs PROPERTIES FOLDER "plugins")
install_obs_plugin_with_data(obs-outputs data)

View file

@ -0,0 +1,4 @@
FLVOutput.FilePath="Файл юлы"
Default="Ғәҙәти"

View file

@ -8,8 +8,8 @@ ConnectionTimedOut="Zeitüberschreitung bei der Verbindung. Stellen Sie sicher,
PermissionDenied="Die Verbindung wurde blockiert. Überprüfen Sie Ihre Firewall/AntiVirusEinstellungen, um sicherzustellen, dass OBS vollen Internetzugang hat."
ConnectionAborted="Die Verbindung wurde abgebrochen. Dies bedeutet in der Regel Probleme mit der Internetverbindung zwischen Ihnen und dem Streamingdienst."
ConnectionReset="Die Verbindung wurde durch den Kommunikationspartner zurückgesetzt. Dies bedeutet in der Regel Probleme mit der Internetverbindung zwischen Ihnen und dem Streamingdienst."
HostNotFound="Hostname nicht gefunden. Stellen Sie sicher, dass Sie einen gültigen Streamingserver eingegeben haben und Ihre Internetverbindung/DNS korrekt arbeiten."
NoData="Hostname gefunden, aber keine Daten des angeforderten Typs vorhanden. Dies kann auftreten, wenn Sie eine IPv6Adresse verwenden, aber Ihr Streamingdienst nur über IPv4Adressen verfügt. (siehe „Einstellungen“ → „Erweitert“)"
AddressNotAvailable="Adresse nicht verfügbar. Sie haben möglicherweise eine ungültige IPAdresse versucht zu verwenden. (siehe „Einstellungen“ → „Erweitert“)"
HostNotFound="Hostname nicht gefunden. Stellen Sie sicher, dass Sie einen gültigen Streamingserver eingegeben haben und Ihr(e) Internetverbindung/DNS korrekt arbeiten."
NoData="Hostname gefunden, aber keine Daten des angeforderten Typs vorhanden. Dies kann auftreten, wenn Sie eine IPv6Adresse verwenden, aber Ihr Streamingdienst nur über IPv4Adressen verfügt. (siehe „Einstellungen“„Erweitert“)"
AddressNotAvailable="Adresse nicht verfügbar. Sie haben möglicherweise eine ungültige IPAdresse versucht zu verwenden. (siehe „Einstellungen“„Erweitert“)"
SSLCertVerifyFailed="Der RTMPServer hat ein ungültiges SSLZertifikat gesendet."

View file

@ -0,0 +1,15 @@
RTMPStream="RTMP Stream"
RTMPStream.DropThreshold="Drop Threshold (milliseconds)"
FLVOutput="FLV File Output"
FLVOutput.FilePath="File Path"
Default="Default"
ConnectionTimedOut="The connection timed out. Make sure you've configured a valid streaming service and no firewall is blocking the connection."
PermissionDenied="The connection was blocked. Check your firewall / anti-virus settings to make sure OBS is allowed full Internet access."
ConnectionAborted="The connection was aborted. This usually indicates Internet connection problems between you and the streaming service."
ConnectionReset="The connection was reset by the peer. This usually indicates Internet connection problems between you and the streaming service."
HostNotFound="Hostname not found. Make sure you entered a valid streaming server and your Internet connection / DNS are working correctly."
NoData="Hostname found, but no data of the requested type. This can occur if you have bound to an IPv6 address and your streaming service only has IPv4 addresses (see Settings → Advanced)."
AddressNotAvailable="Address not available. You may have tried to bind to an invalid IP address (see Settings → Advanced)."
SSLCertVerifyFailed="The RTMP server sent an invalid SSL certificate."

View file

@ -2,6 +2,6 @@ RTMPStream="זרם RTMP"
RTMPStream.DropThreshold="הורד סף (אלפיות שניה)"
FLVOutput="קובץ פלט FLV"
FLVOutput.FilePath="נתיב קובץ"
Default="ברירת מחדל"
Default="ברירת־מחדל"

View file

@ -0,0 +1,15 @@
RTMPStream="Stream RTMP"
RTMPStream.DropThreshold="Ambang Batas Drop (milidetik)"
FLVOutput="Output File FLV"
FLVOutput.FilePath="Lokasi File"
Default="Default"
ConnectionTimedOut="Waktu koneksi habis. Pastikan Anda telah mengkonfigurasi layanan streaming dengan valid dan tidak ada firewall yang memblokir koneksi."
PermissionDenied="Koneksi diblokir. Periksa pengaturan firewall/anti-virus Anda untuk memastikan OBS diizinkan akses internet penuh."
ConnectionAborted="Koneksi dibatalkan. Biasanya mengindikasi masalah koneksi internet antara Anda dan layanan streaming."
ConnectionReset="Koneksi diatur ulang oleh peer. Biasanya mengindikasi masalah koneksi internet antara Anda dan layanan streaming."
HostNotFound="Hostname tidak ditemukan. Pastikan Anda memasukkan server streaming dengan valid dan koneksi internet / DNS Anda berfungsi dengan benar."
NoData="Hostname ditemukan, tetapi tidak ada data dari tipe yang diminta. Ini dapat terjadi jika Anda telah terikat ke alamat IPv6 dan layanan streaming Anda hanya memiliki alamat IPv4 (lihat Pengaturan → Tingkat Lanjut)."
AddressNotAvailable="Alamat tidak tersedia. Anda mungkin mencoba untuk mengikat ke alamat IP yang tidak benar (lihat Pengaturan → Tingkat Lanjut)."
SSLCertVerifyFailed="Server RTMP mengirim sertifikat SSL yang tidak valid."

View file

@ -1,7 +1,15 @@
RTMPStream="Flux RTMP"
RTMPStream.DropThreshold="Prag de pierderi (milisecunde)"
FLVOutput="Ieșire fișier FLV"
FLVOutput="Output fișier FLV"
FLVOutput.FilePath="Calea fișierului"
Default="Implicit"
ConnectionTimedOut="Conexiunea a expirat. Asigură-te că ai configurat un serviciu de streaming valid și că nici un firewall nu blochează conexiunea."
PermissionDenied="Conexiunea a fost blocată. Verificați setările firewall-ului / anti-virus pentru a vă asigura că OBS are acces complet la internet."
ConnectionAborted="Conexiunea a fost întreruptă. Acest lucru indică de obicei probleme de conexiune la internet între dvs. și serviciul de streaming."
ConnectionReset="Conexiunea a fost întreruptă. Acest lucru indică de obicei probleme de conexiune la internet între dvs. și serviciul de streaming."
HostNotFound="Hostname nu a fost găsit. Asigură-te că ai introdus un server valid de streaming și că conexiunea la internet/DNS funcționează corect."
NoData="A fost găsit numele gazdei, dar nu există date de tipul solicitat. Acest lucru poate apărea dacă aveți o adresă IPv6 și serviciul dvs. de streaming are doar adrese IPv4 (vezi Setări → Avansat)."
AddressNotAvailable="Adresa nu este disponibilă. Este posibil să fi încercat conectarea la o adresă IP invalidă (vezi Setări → Avansat)."
SSLCertVerifyFailed="Serverul RTMP a trimis un certificat SSL nevalid."

View file

@ -0,0 +1,6 @@
RTMPStream="RTMP ஸ்ட்ரீம்"
FLVOutput="FLV கோப்பு வெளியீட்டு"
FLVOutput.FilePath="கோப்புப் பாதை"
Default="இயல்புநிலை"

View file

@ -1,15 +1,15 @@
RTMPStream="RTMP потік"
RTMPStream.DropThreshold="Поріг втрат (мілісекунд)"
RTMPStream.DropThreshold="Поріг втрат (мілісекунди)"
FLVOutput="Вивід FLV файлу"
FLVOutput.FilePath="Шлях до файлу"
Default="За замовчанням"
Default="За замовчуванням"
ConnectionTimedOut="Вичерпано час підключення. Переконайтеся, що ви вказали правильний сервіс трансляцій і брандмауер не блокує з'єднання."
PermissionDenied="З'єднання було заблоковано. Перевірте налаштування вашого брандмауеру / антивірусу, щоб переконатися, що OBS має повний доступ до Інтернету."
ConnectionAborted="З'єднання було перервано. Зазвичай свідчить про проблеми з Інтернет підключенням між вами і постачальником з сервісу трансляцій."
ConnectionReset="З'єднання було скинуте рівноправним вузлом (reset by peer). Зазвичай свідчить про проблеми з Інтернет підключенням між вами і постачальником з сервісу трансляцій."
HostNotFound="Ім'я хоста, не знайдено. Переконайтеся, що ви ввели дійсний сервер трансляцій і підключення до Інтернету / DNS працює правильно."
NoData="Ім'я хоста знайдено, але нема жодних даних вказаного типу. Це може статися, якщо ви вказали прив'язку до IPv6-адресу, але ваш сервіс трансляцій підтримує лише адреси IPv4 (див. Налаштування → Розширені)."
AddressNotAvailable="Адреса недоступна. Напевно ви спробували прив'язатись до адаптера з неіснуючою IP-адресою (див. Налаштування → Розширені)."
SSLCertVerifyFailed="RTMP сервер надіслав неприпустимий сертифікат SSL."
ConnectionTimedOut="Час очікування підключення вичерпано. Переконайтеся, що ви вказали коректний сервіс трансляцій і брандмауер не блокує з'єднання."
PermissionDenied="З'єднання було заблоковано. Перевірте налаштування вашого брандмауера / антивірусу, щоб переконатися чи має OBS повний доступ до Інтернету."
ConnectionAborted="З'єднання було перервано. Зазвичай, це свідчить про проблеми з Інтернет підключенням між вами та сервісом трансляцій."
ConnectionReset="З'єднання було скинуте рівноправним вузлом (reset by peer). Зазвичай свідчить про проблеми з Інтернет підключенням між вами та сервісом трансляцій."
HostNotFound="Назву хоста не знайдено. Переконайтеся, що ви ввели дійсний сервер трансляцій і підключення до Інтернету / DNS працює правильно."
NoData="Ім'я хоста знайдено, але нема жодних даних вказаного типу. Це трапляється, якщо ви вказали прив'язку до IPv6-адресу, а ваш сервіс трансляцій підтримує лише адреси IPv4 (див. Налаштування → Розширені)."
AddressNotAvailable="Адреса недоступна. Напевно ви спробували прив'язатись до недійсної IP-адреси (див. Налаштування → Розширені)."
SSLCertVerifyFailed="RTMP сервер надіслав недійсний SSL сертифікат."

View file

@ -30,6 +30,8 @@
//#define WRITE_FLV_HEADER
#define VIDEO_HEADER_SIZE 5
#define VIDEODATA_AVCVIDEOPACKET 7.0
#define AUDIODATA_AAC 10.0
static inline double encoder_bitrate(obs_encoder_t *encoder)
{
@ -56,11 +58,11 @@ void write_file_info(FILE *file, int64_t duration_ms, int64_t size)
fwrite(buf, 1, enc - buf, file);
}
static bool build_flv_meta_data(obs_output_t *context, uint8_t **output,
size_t *size, size_t a_idx)
static void build_flv_meta_data(obs_output_t *context, uint8_t **output,
size_t *size)
{
obs_encoder_t *vencoder = obs_output_get_video_encoder(context);
obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, a_idx);
obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, 0);
video_t *video = obs_encoder_video(vencoder);
audio_t *audio = obs_encoder_audio(aencoder);
char buf[4096];
@ -68,31 +70,25 @@ static bool build_flv_meta_data(obs_output_t *context, uint8_t **output,
char *end = enc + sizeof(buf);
struct dstr encoder_name = {0};
if (a_idx > 0 && !aencoder)
return false;
enc_str(&enc, end, "@setDataFrame");
enc_str(&enc, end, "onMetaData");
*enc++ = AMF_ECMA_ARRAY;
enc = AMF_EncodeInt32(enc, end, a_idx == 0 ? 20 : 15);
enc = AMF_EncodeInt32(enc, end, 20);
enc_num_val(&enc, end, "duration", 0.0);
enc_num_val(&enc, end, "fileSize", 0.0);
if (a_idx == 0) {
enc_num_val(&enc, end, "width",
(double)obs_encoder_get_width(vencoder));
enc_num_val(&enc, end, "height",
(double)obs_encoder_get_height(vencoder));
enc_num_val(&enc, end, "width",
(double)obs_encoder_get_width(vencoder));
enc_num_val(&enc, end, "height",
(double)obs_encoder_get_height(vencoder));
enc_str_val(&enc, end, "videocodecid", "avc1");
enc_num_val(&enc, end, "videodatarate",
encoder_bitrate(vencoder));
enc_num_val(&enc, end, "framerate",
video_output_get_frame_rate(video));
}
enc_num_val(&enc, end, "videocodecid", VIDEODATA_AVCVIDEOPACKET);
enc_num_val(&enc, end, "videodatarate", encoder_bitrate(vencoder));
enc_num_val(&enc, end, "framerate", video_output_get_frame_rate(video));
enc_str_val(&enc, end, "audiocodecid", "mp4a");
enc_num_val(&enc, end, "audiocodecid", AUDIODATA_AAC);
enc_num_val(&enc, end, "audiodatarate", encoder_bitrate(aencoder));
enc_num_val(&enc, end, "audiosamplerate",
(double)obs_encoder_get_sample_rate(aencoder));
@ -129,11 +125,10 @@ static bool build_flv_meta_data(obs_output_t *context, uint8_t **output,
*size = enc - buf;
*output = bmemdup(buf, *size);
return true;
}
bool flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size,
bool write_header, size_t audio_idx)
void flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size,
bool write_header)
{
struct array_output_data data;
struct serializer s;
@ -142,12 +137,7 @@ bool flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size,
uint32_t start_pos;
array_output_serializer_init(&s, &data);
if (!build_flv_meta_data(context, &meta_data, &meta_data_size,
audio_idx)) {
bfree(meta_data);
return false;
}
build_flv_meta_data(context, &meta_data, &meta_data_size);
if (write_header) {
s_write(&s, "FLV", 3);
@ -173,7 +163,6 @@ bool flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size,
*size = data.bytes.num;
bfree(meta_data);
return true;
}
#ifdef DEBUG_TIMESTAMPS
@ -264,3 +253,251 @@ void flv_packet_mux(struct encoder_packet *packet, int32_t dts_offset,
*output = data.bytes.array;
*size = data.bytes.num;
}
/* ------------------------------------------------------------------------- */
/* stuff for additional media streams */
#define s_amf_conststring(s, str) \
do { \
const size_t len = sizeof(str) - 1; \
s_wb16(s, (uint16_t)len); \
serialize(s, str, len); \
} while (false)
#define s_amf_double(s, d) \
do { \
double d_val = d; \
uint64_t u_val = *(uint64_t *)&d_val; \
s_wb64(s, u_val); \
} while (false)
static void flv_build_additional_meta_data(uint8_t **data, size_t *size)
{
struct array_output_data out;
struct serializer s;
array_output_serializer_init(&s, &out);
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "@setDataFrame");
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "onExpectAdditionalMedia");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "processingIntents");
s_w8(&s, AMF_STRICT_ARRAY);
s_wb32(&s, 1);
{
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "ArchiveProgramNarrationAudio");
}
/* ---- */
s_amf_conststring(&s, "additionalMedia");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "stream0");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "type");
s_w8(&s, AMF_NUMBER);
s_amf_double(&s, RTMP_PACKET_TYPE_AUDIO);
/* ---- */
s_amf_conststring(&s, "mediaLabels");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "contentType");
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "PNAR");
}
s_wb24(&s, AMF_OBJECT_END);
}
s_wb24(&s, AMF_OBJECT_END);
}
s_wb24(&s, AMF_OBJECT_END);
/* ---- */
s_amf_conststring(&s, "defaultMedia");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "audio");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "mediaLabels");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "contentType");
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "PRM");
}
s_wb24(&s, AMF_OBJECT_END);
}
s_wb24(&s, AMF_OBJECT_END);
}
s_wb24(&s, AMF_OBJECT_END);
}
s_wb24(&s, AMF_OBJECT_END);
*data = out.bytes.array;
*size = out.bytes.num;
}
void flv_additional_meta_data(obs_output_t *context, uint8_t **data,
size_t *size)
{
UNUSED_PARAMETER(context);
struct array_output_data out;
struct serializer s;
uint8_t *meta_data = NULL;
size_t meta_data_size;
flv_build_additional_meta_data(&meta_data, &meta_data_size);
array_output_serializer_init(&s, &out);
s_w8(&s, RTMP_PACKET_TYPE_INFO); //18
s_wb24(&s, (uint32_t)meta_data_size);
s_wb32(&s, 0);
s_wb24(&s, 0);
s_write(&s, meta_data, meta_data_size);
bfree(meta_data);
s_wb32(&s, (uint32_t)serializer_get_pos(&s) - 1);
*data = out.bytes.array;
*size = out.bytes.num;
}
static inline void s_u29(struct serializer *s, uint32_t val)
{
if (val <= 0x7F) {
s_w8(s, val);
} else if (val <= 0x3FFF) {
s_w8(s, 0x80 | (val >> 7));
s_w8(s, val & 0x7F);
} else if (val <= 0x1FFFFF) {
s_w8(s, 0x80 | (val >> 14));
s_w8(s, 0x80 | ((val >> 7) & 0x7F));
s_w8(s, val & 0x7F);
} else {
s_w8(s, 0x80 | (val >> 22));
s_w8(s, 0x80 | ((val >> 15) & 0x7F));
s_w8(s, 0x80 | ((val >> 8) & 0x7F));
s_w8(s, val & 0xFF);
}
}
static inline void s_u29b_value(struct serializer *s, uint32_t val)
{
s_u29(s, 1 | ((val & 0xFFFFFFF) << 1));
}
static void flv_build_additional_audio(uint8_t **data, size_t *size,
struct encoder_packet *packet,
bool is_header, size_t index)
{
UNUSED_PARAMETER(index);
struct array_output_data out;
struct serializer s;
array_output_serializer_init(&s, &out);
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "additionalMedia");
s_w8(&s, AMF_OBJECT);
{
s_amf_conststring(&s, "id");
s_w8(&s, AMF_STRING);
s_amf_conststring(&s, "stream0");
/* ----- */
s_amf_conststring(&s, "media");
s_w8(&s, AMF_AVMPLUS);
s_w8(&s, AMF3_BYTE_ARRAY);
s_u29b_value(&s, (uint32_t)packet->size + 2);
s_w8(&s, 0xaf);
s_w8(&s, is_header ? 0 : 1);
s_write(&s, packet->data, packet->size);
}
s_wb24(&s, AMF_OBJECT_END);
*data = out.bytes.array;
*size = out.bytes.num;
}
static void flv_additional_audio(struct serializer *s, int32_t dts_offset,
struct encoder_packet *packet, bool is_header,
size_t index)
{
int32_t time_ms = get_ms_time(packet, packet->dts) - dts_offset;
uint8_t *data;
size_t size;
if (!packet->data || !packet->size)
return;
flv_build_additional_audio(&data, &size, packet, is_header, index);
s_w8(s, RTMP_PACKET_TYPE_INFO); //18
#ifdef DEBUG_TIMESTAMPS
blog(LOG_DEBUG, "Audio2: %lu", time_ms);
if (last_time > time_ms)
blog(LOG_DEBUG, "Non-monotonic");
last_time = time_ms;
#endif
s_wb24(s, (uint32_t)size);
s_wb24(s, time_ms);
s_w8(s, (time_ms >> 24) & 0x7F);
s_wb24(s, 0);
serialize(s, data, size);
bfree(data);
s_wb32(s, (uint32_t)serializer_get_pos(s) - 1);
}
void flv_additional_packet_mux(struct encoder_packet *packet,
int32_t dts_offset, uint8_t **data, size_t *size,
bool is_header, size_t index)
{
struct array_output_data out;
struct serializer s;
array_output_serializer_init(&s, &out);
if (packet->type == OBS_ENCODER_VIDEO) {
//currently unsupported
bcrash("who said you could output an additional video packet?");
} else {
flv_additional_audio(&s, dts_offset, packet, is_header, index);
}
*data = out.bytes.array;
*size = out.bytes.num;
}

View file

@ -28,7 +28,13 @@ static int32_t get_ms_time(struct encoder_packet *packet, int64_t val)
extern void write_file_info(FILE *file, int64_t duration_ms, int64_t size);
extern bool flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size,
bool write_header, size_t audio_idx);
extern void flv_meta_data(obs_output_t *context, uint8_t **output, size_t *size,
bool write_header);
extern void flv_additional_meta_data(obs_output_t *context, uint8_t **output,
size_t *size);
extern void flv_packet_mux(struct encoder_packet *packet, int32_t dts_offset,
uint8_t **output, size_t *size, bool is_header);
extern void flv_additional_packet_mux(struct encoder_packet *packet,
int32_t dts_offset, uint8_t **output,
size_t *size, bool is_header,
size_t index);

View file

@ -106,7 +106,7 @@ static void write_meta_data(struct flv_output *stream)
uint8_t *meta_data;
size_t meta_data_size;
flv_meta_data(stream->output, &meta_data, &meta_data_size, true, 0);
flv_meta_data(stream->output, &meta_data, &meta_data_size, true);
fwrite(meta_data, 1, meta_data_size, stream->file);
bfree(meta_data);
}

View file

@ -370,6 +370,7 @@ DHComputeSharedSecretKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen,
MP_gethex(q1, Q1024, len);
assert(len);
UNUSED_PARAMETER(len); // Make GCC happy len is used in release.
if (isValidPublicKey(pubkeyBn, dh->p, q1))
res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh);

View file

@ -322,6 +322,7 @@ HMACsha256(const uint8_t *message, size_t messageLen, const uint8_t *key,
#endif
assert(digestLen == 32);
UNUSED_PARAMETER(digestLen); // Make GCC happy digestLen is used in release.
}
static void

View file

@ -3064,6 +3064,8 @@ static const AVal av_NetStream_Play_UnpublishNotify =
static const AVal av_NetStream_Publish_Start = AVC("NetStream.Publish.Start");
static const AVal av_NetStream_Publish_Rejected = AVC("NetStream.Publish.Rejected");
static const AVal av_NetStream_Publish_Denied = AVC("NetStream.Publish.Denied");
static const AVal av_NetStream_Publish_BadName = AVC("NetStream.Publish.BadName");
/* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */
static int
@ -3314,7 +3316,8 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
|| AVMATCH(&code, &av_NetStream_Play_StreamNotFound)
|| AVMATCH(&code, &av_NetConnection_Connect_InvalidApp)
|| AVMATCH(&code, &av_NetStream_Publish_Rejected)
|| AVMATCH(&code, &av_NetStream_Publish_Denied))
|| AVMATCH(&code, &av_NetStream_Publish_Denied)
|| AVMATCH(&code, &av_NetStream_Publish_BadName))
{
r->m_stream_id = -1;
RTMP_Close(r);
@ -3376,6 +3379,14 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
r->m_pausing = 3;
}
}
else
{
if (description.av_len)
RTMP_Log(RTMP_LOGWARNING, "Unhandled: %s:\n%s (%s)", r->Link.tcUrl.av_val, code.av_val, description.av_val);
else
RTMP_Log(RTMP_LOGWARNING, "Unhandled: %s:\n%s", r->Link.tcUrl.av_val, code.av_val);
}
}
else if (AVMATCH(&method, &av_playlist_ready))
{
@ -5266,13 +5277,11 @@ fail:
return total;
}
static const AVal av_setDataFrame = AVC("@setDataFrame");
int
RTMP_Write(RTMP *r, const char *buf, int size, int streamIdx)
{
RTMPPacket *pkt = &r->m_write;
char *pend, *enc;
char *enc;
int s2 = size, ret, num;
pkt->m_nChannel = 0x04; /* source channel */
@ -5308,8 +5317,6 @@ RTMP_Write(RTMP *r, const char *buf, int size, int streamIdx)
!pkt->m_nTimeStamp) || pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
{
pkt->m_headerType = RTMP_PACKET_SIZE_LARGE;
if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
pkt->m_nBodySize += 16;
}
else
{
@ -5322,12 +5329,6 @@ RTMP_Write(RTMP *r, const char *buf, int size, int streamIdx)
return FALSE;
}
enc = pkt->m_body;
pend = enc + pkt->m_nBodySize;
if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
{
enc = AMF_EncodeString(enc, pend, &av_setDataFrame);
pkt->m_nBytesRead = enc - pkt->m_body;
}
}
else
{

View file

@ -5,6 +5,7 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <mbedtls/threading.h>
#endif
OBS_DECLARE_MODULE()
@ -21,6 +22,37 @@ extern struct obs_output_info flv_output_info;
extern struct obs_output_info ftl_output_info;
#endif
#if defined(_WIN32) && defined(MBEDTLS_THREADING_ALT)
void mbed_mutex_init(mbedtls_threading_mutex_t *m)
{
CRITICAL_SECTION *c = bzalloc(sizeof(CRITICAL_SECTION));
*m = c;
InitializeCriticalSection(c);
}
void mbed_mutex_free(mbedtls_threading_mutex_t *m)
{
CRITICAL_SECTION *c = *m;
DeleteCriticalSection(c);
bfree(*m);
*m = NULL;
}
int mbed_mutex_lock(mbedtls_threading_mutex_t *m)
{
CRITICAL_SECTION *c = *m;
EnterCriticalSection(c);
return 0;
}
int mbed_mutex_unlock(mbedtls_threading_mutex_t *m)
{
CRITICAL_SECTION *c = *m;
LeaveCriticalSection(c);
return 0;
}
#endif
bool obs_module_load(void)
{
#ifdef _WIN32
@ -28,6 +60,11 @@ bool obs_module_load(void)
WSAStartup(MAKEWORD(2, 2), &wsad);
#endif
#if defined(_WIN32) && defined(MBEDTLS_THREADING_ALT)
mbedtls_threading_set_alt(mbed_mutex_init, mbed_mutex_free,
mbed_mutex_lock, mbed_mutex_unlock);
#endif
obs_register_output(&rtmp_output_info);
obs_register_output(&null_output_info);
obs_register_output(&flv_output_info);
@ -40,6 +77,9 @@ bool obs_module_load(void)
void obs_module_unload(void)
{
#ifdef _WIN32
#ifdef MBEDTLS_THREADING_ALT
mbedtls_threading_free_alt();
#endif
WSACleanup();
#endif
}

View file

@ -423,14 +423,20 @@ static int send_packet(struct rtmp_stream *stream,
}
}
flv_packet_mux(packet, is_header ? 0 : stream->start_dts_offset, &data,
&size, is_header);
if (idx > 0) {
flv_additional_packet_mux(
packet, is_header ? 0 : stream->start_dts_offset, &data,
&size, is_header, idx);
} else {
flv_packet_mux(packet, is_header ? 0 : stream->start_dts_offset,
&data, &size, is_header);
}
#ifdef TEST_FRAMEDROPS
droptest_cap_data_rate(stream, size);
#endif
ret = RTMP_Write(&stream->rtmp, (char *)data, (int)size, (int)idx);
ret = RTMP_Write(&stream->rtmp, (char *)data, (int)size, 0);
bfree(data);
if (is_header)
@ -659,20 +665,30 @@ static void *send_thread(void *data)
return NULL;
}
static bool send_meta_data(struct rtmp_stream *stream, size_t idx, bool *next)
static bool send_additional_meta_data(struct rtmp_stream *stream)
{
uint8_t *meta_data;
size_t meta_data_size;
bool success = true;
*next = flv_meta_data(stream->output, &meta_data, &meta_data_size,
false, idx);
flv_additional_meta_data(stream->output, &meta_data, &meta_data_size);
success = RTMP_Write(&stream->rtmp, (char *)meta_data,
(int)meta_data_size, 0) >= 0;
bfree(meta_data);
if (*next) {
success = RTMP_Write(&stream->rtmp, (char *)meta_data,
(int)meta_data_size, (int)idx) >= 0;
bfree(meta_data);
}
return success;
}
static bool send_meta_data(struct rtmp_stream *stream)
{
uint8_t *meta_data;
size_t meta_data_size;
bool success = true;
flv_meta_data(stream->output, &meta_data, &meta_data_size, false);
success = RTMP_Write(&stream->rtmp, (char *)meta_data,
(int)meta_data_size, 0) >= 0;
bfree(meta_data);
return success;
}
@ -761,8 +777,7 @@ static void adjust_sndbuf_size(struct rtmp_stream *stream, int new_size)
static int init_send(struct rtmp_stream *stream)
{
int ret;
size_t idx = 0;
bool next = true;
obs_output_t *context = stream->output;
#if defined(_WIN32)
adjust_sndbuf_size(stream, MIN_SENDBUF_SIZE);
@ -800,7 +815,6 @@ static int init_send(struct rtmp_stream *stream)
bfree(stream->write_buf);
int total_bitrate = 0;
obs_output_t *context = stream->output;
obs_encoder_t *vencoder = obs_output_get_video_encoder(context);
if (vencoder) {
@ -865,14 +879,25 @@ static int init_send(struct rtmp_stream *stream)
}
os_atomic_set_bool(&stream->active, true);
while (next) {
if (!send_meta_data(stream, idx++, &next)) {
warn("Disconnected while attempting to connect to "
"server.");
set_output_error(stream);
return OBS_OUTPUT_DISCONNECTED;
}
if (!send_meta_data(stream)) {
warn("Disconnected while attempting to send metadata");
set_output_error(stream);
return OBS_OUTPUT_DISCONNECTED;
}
obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, 1);
if (aencoder && !send_additional_meta_data(stream)) {
warn("Disconnected while attempting to send additional "
"metadata");
return OBS_OUTPUT_DISCONNECTED;
}
if (obs_output_get_audio_encoder(context, 2) != NULL) {
warn("Additional audio streams not supported");
return OBS_OUTPUT_DISCONNECTED;
}
obs_output_begin_data_capture(stream->output, 0);
return OBS_OUTPUT_SUCCESS;
@ -982,18 +1007,6 @@ static int try_connect(struct rtmp_stream *stream)
RTMP_AddStream(&stream->rtmp, stream->key.array);
for (size_t idx = 1;; idx++) {
obs_encoder_t *encoder =
obs_output_get_audio_encoder(stream->output, idx);
const char *encoder_name;
if (!encoder)
break;
encoder_name = obs_encoder_get_name(encoder);
RTMP_AddStream(&stream->rtmp, encoder_name);
}
stream->rtmp.m_outChunkSize = 4096;
stream->rtmp.m_bSendChunkSizeInfo = true;
stream->rtmp.m_bUseNagle = true;

View file

@ -31,6 +31,7 @@
#define OPT_BIND_IP "bind_ip"
#define OPT_NEWSOCKETLOOP_ENABLED "new_socket_loop_enabled"
#define OPT_LOWLATENCY_ENABLED "low_latency_mode_enabled"
#define OPT_METADATA_MULTITRACK "metadata_multitrack"
//#define TEST_FRAMEDROPS
//#define TEST_FRAMEDROPS_WITH_BITRATE_SHORTCUTS