rtmp-stream.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include "rtmp-stream.h"
  15. #include "rtmp-av1.h"
  16. #include "rtmp-hevc.h"
  17. #include <obs-avc.h>
  18. #include <obs-hevc.h>
  19. #ifdef _WIN32
  20. #include <util/windows/win-version.h>
  21. #endif
  22. #ifndef SEC_TO_NSEC
  23. #define SEC_TO_NSEC 1000000000ULL
  24. #endif
  25. #ifndef MSEC_TO_USEC
  26. #define MSEC_TO_USEC 1000ULL
  27. #endif
  28. #ifndef MSEC_TO_NSEC
  29. #define MSEC_TO_NSEC 1000000ULL
  30. #endif
  31. /* dynamic bitrate coefficients */
  32. #define DBR_INC_TIMER (4ULL * SEC_TO_NSEC)
  33. #define DBR_TRIGGER_USEC (200ULL * MSEC_TO_USEC)
  34. #define MIN_ESTIMATE_DURATION_MS 1000
  35. #define MAX_ESTIMATE_DURATION_MS 2000
  36. static const char *rtmp_stream_getname(void *unused)
  37. {
  38. UNUSED_PARAMETER(unused);
  39. return obs_module_text("RTMPStream");
  40. }
  41. static void log_rtmp(int level, const char *format, va_list args)
  42. {
  43. if (level > RTMP_LOGWARNING)
  44. return;
  45. blogva(LOG_INFO, format, args);
  46. }
  47. static inline size_t num_buffered_packets(struct rtmp_stream *stream);
  48. static inline void free_packets(struct rtmp_stream *stream)
  49. {
  50. size_t num_packets;
  51. pthread_mutex_lock(&stream->packets_mutex);
  52. num_packets = num_buffered_packets(stream);
  53. if (num_packets)
  54. info("Freeing %d remaining packets", (int)num_packets);
  55. while (stream->packets.size) {
  56. struct encoder_packet packet;
  57. deque_pop_front(&stream->packets, &packet, sizeof(packet));
  58. obs_encoder_packet_release(&packet);
  59. }
  60. pthread_mutex_unlock(&stream->packets_mutex);
  61. }
  62. static inline bool stopping(struct rtmp_stream *stream)
  63. {
  64. return os_event_try(stream->stop_event) != EAGAIN;
  65. }
  66. static inline bool connecting(struct rtmp_stream *stream)
  67. {
  68. return os_atomic_load_bool(&stream->connecting);
  69. }
  70. static inline bool active(struct rtmp_stream *stream)
  71. {
  72. return os_atomic_load_bool(&stream->active);
  73. }
  74. static inline bool disconnected(struct rtmp_stream *stream)
  75. {
  76. return os_atomic_load_bool(&stream->disconnected);
  77. }
  78. static void rtmp_stream_destroy(void *data)
  79. {
  80. struct rtmp_stream *stream = data;
  81. if (stopping(stream) && !connecting(stream)) {
  82. pthread_join(stream->send_thread, NULL);
  83. } else if (connecting(stream) || active(stream)) {
  84. if (stream->connecting)
  85. pthread_join(stream->connect_thread, NULL);
  86. stream->stop_ts = 0;
  87. os_event_signal(stream->stop_event);
  88. if (active(stream)) {
  89. os_sem_post(stream->send_sem);
  90. obs_output_end_data_capture(stream->output);
  91. pthread_join(stream->send_thread, NULL);
  92. }
  93. }
  94. RTMP_TLS_Free(&stream->rtmp);
  95. free_packets(stream);
  96. dstr_free(&stream->path);
  97. dstr_free(&stream->key);
  98. dstr_free(&stream->username);
  99. dstr_free(&stream->password);
  100. dstr_free(&stream->encoder_name);
  101. dstr_free(&stream->bind_ip);
  102. os_event_destroy(stream->stop_event);
  103. os_sem_destroy(stream->send_sem);
  104. pthread_mutex_destroy(&stream->packets_mutex);
  105. deque_free(&stream->packets);
  106. #ifdef TEST_FRAMEDROPS
  107. deque_free(&stream->droptest_info);
  108. #endif
  109. deque_free(&stream->dbr_frames);
  110. pthread_mutex_destroy(&stream->dbr_mutex);
  111. os_event_destroy(stream->buffer_space_available_event);
  112. os_event_destroy(stream->buffer_has_data_event);
  113. os_event_destroy(stream->socket_available_event);
  114. os_event_destroy(stream->send_thread_signaled_exit);
  115. pthread_mutex_destroy(&stream->write_buf_mutex);
  116. if (stream->write_buf)
  117. bfree(stream->write_buf);
  118. bfree(stream);
  119. }
  120. static void *rtmp_stream_create(obs_data_t *settings, obs_output_t *output)
  121. {
  122. struct rtmp_stream *stream = bzalloc(sizeof(struct rtmp_stream));
  123. stream->output = output;
  124. pthread_mutex_init_value(&stream->packets_mutex);
  125. RTMP_LogSetCallback(log_rtmp);
  126. RTMP_LogSetLevel(RTMP_LOGWARNING);
  127. if (pthread_mutex_init(&stream->packets_mutex, NULL) != 0)
  128. goto fail;
  129. if (os_event_init(&stream->stop_event, OS_EVENT_TYPE_MANUAL) != 0)
  130. goto fail;
  131. if (pthread_mutex_init(&stream->write_buf_mutex, NULL) != 0) {
  132. warn("Failed to initialize write buffer mutex");
  133. goto fail;
  134. }
  135. if (pthread_mutex_init(&stream->dbr_mutex, NULL) != 0) {
  136. warn("Failed to initialize dbr mutex");
  137. goto fail;
  138. }
  139. if (os_event_init(&stream->buffer_space_available_event,
  140. OS_EVENT_TYPE_AUTO) != 0) {
  141. warn("Failed to initialize write buffer event");
  142. goto fail;
  143. }
  144. if (os_event_init(&stream->buffer_has_data_event, OS_EVENT_TYPE_AUTO) !=
  145. 0) {
  146. warn("Failed to initialize data buffer event");
  147. goto fail;
  148. }
  149. if (os_event_init(&stream->socket_available_event,
  150. OS_EVENT_TYPE_AUTO) != 0) {
  151. warn("Failed to initialize socket buffer event");
  152. goto fail;
  153. }
  154. if (os_event_init(&stream->send_thread_signaled_exit,
  155. OS_EVENT_TYPE_MANUAL) != 0) {
  156. warn("Failed to initialize socket exit event");
  157. goto fail;
  158. }
  159. UNUSED_PARAMETER(settings);
  160. return stream;
  161. fail:
  162. rtmp_stream_destroy(stream);
  163. return NULL;
  164. }
  165. static void rtmp_stream_stop(void *data, uint64_t ts)
  166. {
  167. struct rtmp_stream *stream = data;
  168. if (stopping(stream) && ts != 0)
  169. return;
  170. if (connecting(stream))
  171. pthread_join(stream->connect_thread, NULL);
  172. stream->stop_ts = ts / 1000ULL;
  173. if (ts)
  174. stream->shutdown_timeout_ts =
  175. ts +
  176. (uint64_t)stream->max_shutdown_time_sec * 1000000000ULL;
  177. if (active(stream)) {
  178. os_event_signal(stream->stop_event);
  179. if (stream->stop_ts == 0)
  180. os_sem_post(stream->send_sem);
  181. } else {
  182. obs_output_signal_stop(stream->output, OBS_OUTPUT_SUCCESS);
  183. }
  184. }
  185. static inline void set_rtmp_dstr(AVal *val, struct dstr *str)
  186. {
  187. bool valid = !dstr_is_empty(str);
  188. val->av_val = valid ? str->array : NULL;
  189. val->av_len = valid ? (int)str->len : 0;
  190. }
  191. static inline bool get_next_packet(struct rtmp_stream *stream,
  192. struct encoder_packet *packet)
  193. {
  194. bool new_packet = false;
  195. pthread_mutex_lock(&stream->packets_mutex);
  196. if (stream->packets.size) {
  197. deque_pop_front(&stream->packets, packet,
  198. sizeof(struct encoder_packet));
  199. new_packet = true;
  200. }
  201. pthread_mutex_unlock(&stream->packets_mutex);
  202. return new_packet;
  203. }
  204. static bool process_recv_data(struct rtmp_stream *stream, size_t size)
  205. {
  206. UNUSED_PARAMETER(size);
  207. RTMP *rtmp = &stream->rtmp;
  208. RTMPPacket packet = {0};
  209. if (!RTMP_ReadPacket(rtmp, &packet)) {
  210. #ifdef _WIN32
  211. int error = WSAGetLastError();
  212. #else
  213. int error = errno;
  214. #endif
  215. do_log(LOG_ERROR, "RTMP_ReadPacket error: %d", error);
  216. return false;
  217. }
  218. if (packet.m_body) {
  219. /* do processing here */
  220. RTMPPacket_Free(&packet);
  221. }
  222. return true;
  223. }
  224. #ifdef TEST_FRAMEDROPS
  225. static void droptest_cap_data_rate(struct rtmp_stream *stream, size_t size)
  226. {
  227. uint64_t ts = os_gettime_ns();
  228. struct droptest_info info;
  229. #if defined(_WIN32) && defined(TEST_FRAMEDROPS_WITH_BITRATE_SHORTCUTS)
  230. uint64_t check_elapsed = ts - stream->droptest_last_key_check;
  231. if (check_elapsed > (200ULL * MSEC_TO_NSEC)) {
  232. size_t bitrate = 0;
  233. stream->droptest_last_key_check = ts;
  234. if (GetAsyncKeyState(VK_NUMPAD0) & 0x8000) {
  235. stream->droptest_max = 0;
  236. } else if (GetAsyncKeyState(VK_NUMPAD1) & 0x8000) {
  237. bitrate = 1000;
  238. } else if (GetAsyncKeyState(VK_NUMPAD2) & 0x8000) {
  239. bitrate = 2000;
  240. } else if (GetAsyncKeyState(VK_NUMPAD3) & 0x8000) {
  241. bitrate = 3000;
  242. } else if (GetAsyncKeyState(VK_NUMPAD4) & 0x8000) {
  243. bitrate = 4000;
  244. } else if (GetAsyncKeyState(VK_NUMPAD5) & 0x8000) {
  245. bitrate = 5000;
  246. } else if (GetAsyncKeyState(VK_NUMPAD6) & 0x8000) {
  247. bitrate = 6000;
  248. } else if (GetAsyncKeyState(VK_NUMPAD7) & 0x8000) {
  249. bitrate = 7000;
  250. } else if (GetAsyncKeyState(VK_NUMPAD8) & 0x8000) {
  251. bitrate = 8000;
  252. } else if (GetAsyncKeyState(VK_NUMPAD9) & 0x8000) {
  253. bitrate = 9000;
  254. }
  255. if (bitrate) {
  256. stream->droptest_max = (bitrate * 1000 / 8);
  257. }
  258. }
  259. if (!stream->droptest_max) {
  260. return;
  261. }
  262. #else
  263. if (!stream->droptest_max) {
  264. stream->droptest_max = DROPTEST_MAX_BYTES;
  265. }
  266. #endif
  267. info.ts = ts;
  268. info.size = size;
  269. deque_push_back(&stream->droptest_info, &info, sizeof(info));
  270. stream->droptest_size += size;
  271. if (stream->droptest_info.size) {
  272. deque_peek_front(&stream->droptest_info, &info, sizeof(info));
  273. if (stream->droptest_size > stream->droptest_max) {
  274. uint64_t elapsed = ts - info.ts;
  275. if (elapsed < 1000000000ULL) {
  276. elapsed = 1000000000ULL - elapsed;
  277. os_sleepto_ns(ts + elapsed);
  278. }
  279. while (stream->droptest_size > stream->droptest_max) {
  280. deque_pop_front(&stream->droptest_info, &info,
  281. sizeof(info));
  282. stream->droptest_size -= info.size;
  283. }
  284. }
  285. }
  286. }
  287. #endif
  288. static int socket_queue_data(RTMPSockBuf *sb, const char *data, int len,
  289. void *arg)
  290. {
  291. UNUSED_PARAMETER(sb);
  292. struct rtmp_stream *stream = arg;
  293. retry_send:
  294. if (!RTMP_IsConnected(&stream->rtmp))
  295. return 0;
  296. pthread_mutex_lock(&stream->write_buf_mutex);
  297. if (stream->write_buf_len + len > stream->write_buf_size) {
  298. pthread_mutex_unlock(&stream->write_buf_mutex);
  299. if (os_event_wait(stream->buffer_space_available_event)) {
  300. return 0;
  301. }
  302. goto retry_send;
  303. }
  304. memcpy(stream->write_buf + stream->write_buf_len, data, len);
  305. stream->write_buf_len += len;
  306. pthread_mutex_unlock(&stream->write_buf_mutex);
  307. os_event_signal(stream->buffer_has_data_event);
  308. return len;
  309. }
  310. static int handle_socket_read(struct rtmp_stream *stream)
  311. {
  312. int ret = 0;
  313. int recv_size = 0;
  314. if (!stream->new_socket_loop) {
  315. #ifdef _WIN32
  316. ret = ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONREAD,
  317. (u_long *)&recv_size);
  318. #else
  319. ret = ioctl(stream->rtmp.m_sb.sb_socket, FIONREAD, &recv_size);
  320. #endif
  321. if (ret >= 0 && recv_size > 0) {
  322. if (!process_recv_data(stream, (size_t)recv_size))
  323. return -1;
  324. }
  325. }
  326. return 0;
  327. }
  328. static int send_packet(struct rtmp_stream *stream,
  329. struct encoder_packet *packet, bool is_header,
  330. size_t idx)
  331. {
  332. uint8_t *data;
  333. size_t size;
  334. int ret = 0;
  335. assert(idx < RTMP_MAX_STREAMS);
  336. if (handle_socket_read(stream))
  337. return -1;
  338. if (idx > 0) {
  339. flv_additional_packet_mux(
  340. packet, is_header ? 0 : stream->start_dts_offset, &data,
  341. &size, is_header, idx);
  342. } else {
  343. flv_packet_mux(packet, is_header ? 0 : stream->start_dts_offset,
  344. &data, &size, is_header);
  345. }
  346. #ifdef TEST_FRAMEDROPS
  347. droptest_cap_data_rate(stream, size);
  348. #endif
  349. ret = RTMP_Write(&stream->rtmp, (char *)data, (int)size, 0);
  350. bfree(data);
  351. if (is_header)
  352. bfree(packet->data);
  353. else
  354. obs_encoder_packet_release(packet);
  355. stream->total_bytes_sent += size;
  356. return ret;
  357. }
  358. static int send_packet_ex(struct rtmp_stream *stream,
  359. struct encoder_packet *packet, bool is_header,
  360. bool is_footer, size_t idx)
  361. {
  362. uint8_t *data;
  363. size_t size = 0;
  364. int ret = 0;
  365. if (handle_socket_read(stream))
  366. return -1;
  367. if (is_header) {
  368. flv_packet_start(packet, stream->video_codec[idx], &data, &size,
  369. idx);
  370. } else if (is_footer) {
  371. flv_packet_end(packet, stream->video_codec[idx], &data, &size,
  372. idx);
  373. } else {
  374. flv_packet_frames(packet, stream->video_codec[idx],
  375. stream->start_dts_offset, &data, &size, idx);
  376. }
  377. #ifdef TEST_FRAMEDROPS
  378. droptest_cap_data_rate(stream, size);
  379. #endif
  380. ret = RTMP_Write(&stream->rtmp, (char *)data, (int)size, 0);
  381. bfree(data);
  382. if (is_header || is_footer) // manually created packets
  383. bfree(packet->data);
  384. else
  385. obs_encoder_packet_release(packet);
  386. stream->total_bytes_sent += size;
  387. return ret;
  388. }
  389. static inline bool send_headers(struct rtmp_stream *stream);
  390. static inline bool send_footers(struct rtmp_stream *stream);
  391. static inline bool can_shutdown_stream(struct rtmp_stream *stream,
  392. struct encoder_packet *packet)
  393. {
  394. uint64_t cur_time = os_gettime_ns();
  395. bool timeout = cur_time >= stream->shutdown_timeout_ts;
  396. if (timeout)
  397. info("Stream shutdown timeout reached (%d second(s))",
  398. stream->max_shutdown_time_sec);
  399. return timeout || packet->sys_dts_usec >= (int64_t)stream->stop_ts;
  400. }
  401. static void set_output_error(struct rtmp_stream *stream)
  402. {
  403. const char *msg = NULL;
  404. #ifdef _WIN32
  405. switch (stream->rtmp.last_error_code) {
  406. case WSAETIMEDOUT:
  407. msg = obs_module_text("ConnectionTimedOut");
  408. break;
  409. case WSAEACCES:
  410. msg = obs_module_text("PermissionDenied");
  411. break;
  412. case WSAECONNABORTED:
  413. msg = obs_module_text("ConnectionAborted");
  414. break;
  415. case WSAECONNRESET:
  416. msg = obs_module_text("ConnectionReset");
  417. break;
  418. case WSAHOST_NOT_FOUND:
  419. msg = obs_module_text("HostNotFound");
  420. break;
  421. case WSANO_DATA:
  422. msg = obs_module_text("NoData");
  423. break;
  424. case WSAEADDRNOTAVAIL:
  425. msg = obs_module_text("AddressNotAvailable");
  426. break;
  427. case WSAEINVAL:
  428. msg = obs_module_text("InvalidParameter");
  429. break;
  430. case WSAEHOSTUNREACH:
  431. msg = obs_module_text("NoRoute");
  432. break;
  433. }
  434. #else
  435. switch (stream->rtmp.last_error_code) {
  436. case ETIMEDOUT:
  437. msg = obs_module_text("ConnectionTimedOut");
  438. break;
  439. case EACCES:
  440. msg = obs_module_text("PermissionDenied");
  441. break;
  442. case ECONNABORTED:
  443. msg = obs_module_text("ConnectionAborted");
  444. break;
  445. case ECONNRESET:
  446. msg = obs_module_text("ConnectionReset");
  447. break;
  448. case HOST_NOT_FOUND:
  449. msg = obs_module_text("HostNotFound");
  450. break;
  451. case NO_DATA:
  452. msg = obs_module_text("NoData");
  453. break;
  454. case EADDRNOTAVAIL:
  455. msg = obs_module_text("AddressNotAvailable");
  456. break;
  457. case EINVAL:
  458. msg = obs_module_text("InvalidParameter");
  459. break;
  460. case EHOSTUNREACH:
  461. msg = obs_module_text("NoRoute");
  462. break;
  463. }
  464. #endif
  465. // non platform-specific errors
  466. if (!msg) {
  467. switch (stream->rtmp.last_error_code) {
  468. case -0x2700:
  469. msg = obs_module_text("SSLCertVerifyFailed");
  470. break;
  471. case -0x7680:
  472. msg = "Failed to load root certificates for a secure TLS connection."
  473. #if defined(__linux__)
  474. " Check you have an up to date root certificate bundle in /etc/ssl/certs."
  475. #endif
  476. ;
  477. break;
  478. }
  479. }
  480. if (msg)
  481. obs_output_set_last_error(stream->output, msg);
  482. }
  483. static void dbr_add_frame(struct rtmp_stream *stream, struct dbr_frame *back)
  484. {
  485. struct dbr_frame front;
  486. uint64_t dur;
  487. deque_push_back(&stream->dbr_frames, back, sizeof(*back));
  488. deque_peek_front(&stream->dbr_frames, &front, sizeof(front));
  489. stream->dbr_data_size += back->size;
  490. dur = (back->send_end - front.send_beg) / 1000000;
  491. if (dur >= MAX_ESTIMATE_DURATION_MS) {
  492. stream->dbr_data_size -= front.size;
  493. deque_pop_front(&stream->dbr_frames, NULL, sizeof(front));
  494. }
  495. stream->dbr_est_bitrate =
  496. (dur >= MIN_ESTIMATE_DURATION_MS)
  497. ? (long)(stream->dbr_data_size * 1000 / dur)
  498. : 0;
  499. stream->dbr_est_bitrate *= 8;
  500. stream->dbr_est_bitrate /= 1000;
  501. if (stream->dbr_est_bitrate) {
  502. stream->dbr_est_bitrate -= stream->audio_bitrate;
  503. if (stream->dbr_est_bitrate < 50)
  504. stream->dbr_est_bitrate = 50;
  505. }
  506. }
  507. static void dbr_set_bitrate(struct rtmp_stream *stream);
  508. #ifdef _WIN32
  509. #define socklen_t int
  510. #endif
  511. static void log_sndbuf_size(struct rtmp_stream *stream)
  512. {
  513. int cur_sendbuf_size;
  514. socklen_t int_size = sizeof(int);
  515. if (!getsockopt(stream->rtmp.m_sb.sb_socket, SOL_SOCKET, SO_SNDBUF,
  516. (char *)&cur_sendbuf_size, &int_size)) {
  517. info("Socket send buffer is %d bytes", cur_sendbuf_size);
  518. }
  519. }
  520. static void *send_thread(void *data)
  521. {
  522. struct rtmp_stream *stream = data;
  523. os_set_thread_name("rtmp-stream: send_thread");
  524. #if defined(_WIN32)
  525. log_sndbuf_size(stream);
  526. #endif
  527. while (os_sem_wait(stream->send_sem) == 0) {
  528. struct encoder_packet packet;
  529. struct dbr_frame dbr_frame;
  530. if (stopping(stream) && stream->stop_ts == 0) {
  531. break;
  532. }
  533. if (!get_next_packet(stream, &packet))
  534. continue;
  535. if (stopping(stream)) {
  536. if (can_shutdown_stream(stream, &packet)) {
  537. obs_encoder_packet_release(&packet);
  538. break;
  539. }
  540. }
  541. if (!stream->sent_headers) {
  542. if (!send_headers(stream)) {
  543. os_atomic_set_bool(&stream->disconnected, true);
  544. break;
  545. }
  546. }
  547. if (stream->dbr_enabled) {
  548. dbr_frame.send_beg = os_gettime_ns();
  549. dbr_frame.size = packet.size;
  550. }
  551. int sent;
  552. if (packet.type == OBS_ENCODER_VIDEO &&
  553. (stream->video_codec[packet.track_idx] != CODEC_H264 ||
  554. (stream->video_codec[packet.track_idx] == CODEC_H264 &&
  555. packet.track_idx != 0))) {
  556. sent = send_packet_ex(stream, &packet, false, false,
  557. packet.track_idx);
  558. } else {
  559. sent = send_packet(stream, &packet, false,
  560. packet.track_idx);
  561. }
  562. if (sent < 0) {
  563. os_atomic_set_bool(&stream->disconnected, true);
  564. break;
  565. }
  566. if (stream->dbr_enabled) {
  567. dbr_frame.send_end = os_gettime_ns();
  568. pthread_mutex_lock(&stream->dbr_mutex);
  569. dbr_add_frame(stream, &dbr_frame);
  570. pthread_mutex_unlock(&stream->dbr_mutex);
  571. }
  572. }
  573. bool encode_error = os_atomic_load_bool(&stream->encode_error);
  574. if (disconnected(stream)) {
  575. info("Disconnected from %s", stream->path.array);
  576. } else if (encode_error) {
  577. info("Encoder error, disconnecting");
  578. send_footers(stream); // Y2023 spec
  579. } else {
  580. info("User stopped the stream");
  581. send_footers(stream); // Y2023 spec
  582. }
  583. #if defined(_WIN32)
  584. log_sndbuf_size(stream);
  585. #endif
  586. if (stream->new_socket_loop) {
  587. os_event_signal(stream->send_thread_signaled_exit);
  588. os_event_signal(stream->buffer_has_data_event);
  589. pthread_join(stream->socket_thread, NULL);
  590. stream->socket_thread_active = false;
  591. stream->rtmp.m_bCustomSend = false;
  592. }
  593. set_output_error(stream);
  594. RTMP_Close(&stream->rtmp);
  595. /* reset bitrate on stop */
  596. if (stream->dbr_enabled) {
  597. if (stream->dbr_cur_bitrate != stream->dbr_orig_bitrate) {
  598. stream->dbr_cur_bitrate = stream->dbr_orig_bitrate;
  599. dbr_set_bitrate(stream);
  600. }
  601. }
  602. if (!stopping(stream)) {
  603. pthread_detach(stream->send_thread);
  604. obs_output_signal_stop(stream->output, OBS_OUTPUT_DISCONNECTED);
  605. } else if (encode_error) {
  606. obs_output_signal_stop(stream->output, OBS_OUTPUT_ENCODE_ERROR);
  607. } else {
  608. obs_output_end_data_capture(stream->output);
  609. }
  610. free_packets(stream);
  611. os_event_reset(stream->stop_event);
  612. os_atomic_set_bool(&stream->active, false);
  613. stream->sent_headers = false;
  614. return NULL;
  615. }
  616. static bool send_additional_meta_data(struct rtmp_stream *stream)
  617. {
  618. uint8_t *meta_data;
  619. size_t meta_data_size;
  620. bool success = true;
  621. flv_additional_meta_data(stream->output, &meta_data, &meta_data_size);
  622. success = RTMP_Write(&stream->rtmp, (char *)meta_data,
  623. (int)meta_data_size, 0) >= 0;
  624. bfree(meta_data);
  625. return success;
  626. }
  627. static bool send_meta_data(struct rtmp_stream *stream)
  628. {
  629. uint8_t *meta_data;
  630. size_t meta_data_size;
  631. bool success = true;
  632. flv_meta_data(stream->output, &meta_data, &meta_data_size, false);
  633. success = RTMP_Write(&stream->rtmp, (char *)meta_data,
  634. (int)meta_data_size, 0) >= 0;
  635. bfree(meta_data);
  636. return success;
  637. }
  638. static bool send_audio_header(struct rtmp_stream *stream, size_t idx,
  639. bool *next)
  640. {
  641. obs_output_t *context = stream->output;
  642. obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, idx);
  643. uint8_t *header;
  644. struct encoder_packet packet = {.type = OBS_ENCODER_AUDIO,
  645. .timebase_den = 1};
  646. if (!aencoder) {
  647. *next = false;
  648. return true;
  649. }
  650. if (!obs_encoder_get_extra_data(aencoder, &header, &packet.size))
  651. return false;
  652. packet.data = bmemdup(header, packet.size);
  653. return send_packet(stream, &packet, true, idx) >= 0;
  654. }
  655. static bool send_video_header(struct rtmp_stream *stream, size_t idx)
  656. {
  657. obs_output_t *context = stream->output;
  658. obs_encoder_t *vencoder = obs_output_get_video_encoder2(context, idx);
  659. uint8_t *header;
  660. size_t size;
  661. struct encoder_packet packet = {.type = OBS_ENCODER_VIDEO,
  662. .timebase_den = 1,
  663. .keyframe = true};
  664. if (!vencoder)
  665. return false;
  666. if (!obs_encoder_get_extra_data(vencoder, &header, &size))
  667. return false;
  668. switch (stream->video_codec[idx]) {
  669. case CODEC_H264:
  670. packet.size = obs_parse_avc_header(&packet.data, header, size);
  671. // Always send H.264 on track 0 as old style for compatibility.
  672. if (idx == 0) {
  673. return send_packet(stream, &packet, true, idx) >= 0;
  674. } else {
  675. return send_packet_ex(stream, &packet, true, false,
  676. idx) >= 0;
  677. }
  678. case CODEC_HEVC:
  679. #ifdef ENABLE_HEVC
  680. packet.size = obs_parse_hevc_header(&packet.data, header, size);
  681. return send_packet_ex(stream, &packet, true, false, idx) >= 0;
  682. #else
  683. return false;
  684. #endif
  685. case CODEC_AV1:
  686. packet.size = obs_parse_av1_header(&packet.data, header, size);
  687. return send_packet_ex(stream, &packet, true, false, idx) >= 0;
  688. }
  689. return false;
  690. }
  691. // only returns false if there's an error, not if no metadata needs to be sent
  692. static bool send_video_metadata(struct rtmp_stream *stream, size_t idx)
  693. {
  694. // send metadata only if HDR
  695. obs_encoder_t *encoder =
  696. obs_output_get_video_encoder2(stream->output, idx);
  697. if (!encoder)
  698. return false;
  699. video_t *video = obs_encoder_video(encoder);
  700. if (!video)
  701. return false;
  702. const struct video_output_info *info = video_output_get_info(video);
  703. enum video_colorspace colorspace = info->colorspace;
  704. if (!(colorspace == VIDEO_CS_2100_PQ ||
  705. colorspace == VIDEO_CS_2100_HLG))
  706. return true;
  707. if (handle_socket_read(stream))
  708. return false;
  709. // Y2023 spec
  710. if (stream->video_codec[idx] != CODEC_H264) {
  711. uint8_t *data;
  712. size_t size;
  713. video_t *video = obs_get_video();
  714. const struct video_output_info *info =
  715. video_output_get_info(video);
  716. enum video_format format = info->format;
  717. enum video_colorspace colorspace = info->colorspace;
  718. int bits_per_raw_sample;
  719. switch (format) {
  720. case VIDEO_FORMAT_I010:
  721. case VIDEO_FORMAT_P010:
  722. case VIDEO_FORMAT_I210:
  723. bits_per_raw_sample = 10;
  724. break;
  725. case VIDEO_FORMAT_I412:
  726. case VIDEO_FORMAT_YA2L:
  727. bits_per_raw_sample = 12;
  728. break;
  729. default:
  730. bits_per_raw_sample = 8;
  731. }
  732. int pri = 0, trc = 0, spc = 0;
  733. switch (colorspace) {
  734. case VIDEO_CS_601:
  735. pri = OBSCOL_PRI_SMPTE170M;
  736. trc = OBSCOL_PRI_SMPTE170M;
  737. spc = OBSCOL_PRI_SMPTE170M;
  738. break;
  739. case VIDEO_CS_DEFAULT:
  740. case VIDEO_CS_709:
  741. pri = OBSCOL_PRI_BT709;
  742. trc = OBSCOL_PRI_BT709;
  743. spc = OBSCOL_PRI_BT709;
  744. break;
  745. case VIDEO_CS_SRGB:
  746. pri = OBSCOL_PRI_BT709;
  747. trc = OBSCOL_TRC_IEC61966_2_1;
  748. spc = OBSCOL_PRI_BT709;
  749. break;
  750. case VIDEO_CS_2100_PQ:
  751. pri = OBSCOL_PRI_BT2020;
  752. trc = OBSCOL_TRC_SMPTE2084;
  753. spc = OBSCOL_SPC_BT2020_NCL;
  754. break;
  755. case VIDEO_CS_2100_HLG:
  756. pri = OBSCOL_PRI_BT2020;
  757. trc = OBSCOL_TRC_ARIB_STD_B67;
  758. spc = OBSCOL_SPC_BT2020_NCL;
  759. }
  760. int max_luminance = 0;
  761. if (trc == OBSCOL_TRC_ARIB_STD_B67)
  762. max_luminance = 1000;
  763. else if (trc == OBSCOL_TRC_SMPTE2084)
  764. max_luminance =
  765. (int)obs_get_video_hdr_nominal_peak_level();
  766. flv_packet_metadata(stream->video_codec[idx], &data, &size,
  767. bits_per_raw_sample, pri, trc, spc, 0,
  768. max_luminance, idx);
  769. int ret = RTMP_Write(&stream->rtmp, (char *)data, (int)size, 0);
  770. bfree(data);
  771. stream->total_bytes_sent += size;
  772. return ret >= 0;
  773. }
  774. // legacy
  775. return true;
  776. }
  777. static bool send_video_footer(struct rtmp_stream *stream, size_t idx)
  778. {
  779. struct encoder_packet packet = {.type = OBS_ENCODER_VIDEO,
  780. .timebase_den = 1,
  781. .keyframe = false};
  782. packet.size = 0;
  783. return send_packet_ex(stream, &packet, false, true, idx) >= 0;
  784. }
  785. static inline bool send_headers(struct rtmp_stream *stream)
  786. {
  787. stream->sent_headers = true;
  788. size_t i = 0;
  789. bool next = true;
  790. if (!send_audio_header(stream, i++, &next))
  791. return false;
  792. for (size_t j = 0; j < MAX_OUTPUT_VIDEO_ENCODERS; j++) {
  793. obs_output_t *enc =
  794. obs_output_get_video_encoder2(stream->output, j);
  795. if (!enc)
  796. continue;
  797. if (!send_video_metadata(stream, j) ||
  798. !send_video_header(stream, j))
  799. return false;
  800. }
  801. while (next) {
  802. if (!send_audio_header(stream, i++, &next))
  803. return false;
  804. }
  805. return true;
  806. }
  807. static inline bool send_footers(struct rtmp_stream *stream)
  808. {
  809. for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) {
  810. obs_encoder_t *encoder =
  811. obs_output_get_video_encoder2(stream->output, i);
  812. if (!encoder)
  813. continue;
  814. if (i == 0 && stream->video_codec[i] == CODEC_H264)
  815. continue;
  816. if (!send_video_footer(stream, i))
  817. return false;
  818. }
  819. return true;
  820. }
  821. static inline bool reset_semaphore(struct rtmp_stream *stream)
  822. {
  823. os_sem_destroy(stream->send_sem);
  824. return os_sem_init(&stream->send_sem, 0) == 0;
  825. }
  826. static int init_send(struct rtmp_stream *stream)
  827. {
  828. int ret;
  829. obs_output_t *context = stream->output;
  830. reset_semaphore(stream);
  831. ret = pthread_create(&stream->send_thread, NULL, send_thread, stream);
  832. if (ret != 0) {
  833. RTMP_Close(&stream->rtmp);
  834. warn("Failed to create send thread");
  835. return OBS_OUTPUT_ERROR;
  836. }
  837. if (stream->new_socket_loop) {
  838. int one = 1;
  839. #ifdef _WIN32
  840. if (ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) {
  841. stream->rtmp.last_error_code = WSAGetLastError();
  842. #else
  843. if (ioctl(stream->rtmp.m_sb.sb_socket, FIONBIO, &one)) {
  844. stream->rtmp.last_error_code = errno;
  845. #endif
  846. warn("Failed to set non-blocking socket");
  847. return OBS_OUTPUT_ERROR;
  848. }
  849. os_event_reset(stream->send_thread_signaled_exit);
  850. info("New socket loop enabled by user");
  851. if (stream->low_latency_mode)
  852. info("Low latency mode enabled by user");
  853. if (stream->write_buf)
  854. bfree(stream->write_buf);
  855. int total_bitrate = 0;
  856. for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) {
  857. obs_encoder_t *vencoder =
  858. obs_output_get_video_encoder2(context, i);
  859. if (!vencoder)
  860. continue;
  861. obs_data_t *params = obs_encoder_get_settings(vencoder);
  862. if (params) {
  863. int bitrate =
  864. obs_data_get_int(params, "bitrate");
  865. if (!bitrate) {
  866. warn("Video encoder didn't return a "
  867. "valid bitrate, new network "
  868. "code may function poorly. "
  869. "Low latency mode disabled.");
  870. stream->low_latency_mode = false;
  871. bitrate = 10000;
  872. }
  873. total_bitrate += bitrate;
  874. obs_data_release(params);
  875. }
  876. }
  877. obs_encoder_t *aencoder =
  878. obs_output_get_audio_encoder(context, 0);
  879. if (aencoder) {
  880. obs_data_t *params = obs_encoder_get_settings(aencoder);
  881. if (params) {
  882. int bitrate =
  883. obs_data_get_int(params, "bitrate");
  884. if (!bitrate)
  885. bitrate = 160;
  886. total_bitrate += bitrate;
  887. obs_data_release(params);
  888. }
  889. }
  890. // to bytes/sec
  891. int ideal_buffer_size = total_bitrate * 128;
  892. if (ideal_buffer_size < 131072)
  893. ideal_buffer_size = 131072;
  894. stream->write_buf_size = ideal_buffer_size;
  895. stream->write_buf = bmalloc(ideal_buffer_size);
  896. #ifndef _WIN32
  897. warn("New socket loop not supported on this platform");
  898. return OBS_OUTPUT_ERROR;
  899. #else
  900. ret = pthread_create(&stream->socket_thread, NULL,
  901. socket_thread_windows, stream);
  902. if (ret != 0) {
  903. RTMP_Close(&stream->rtmp);
  904. warn("Failed to create socket thread");
  905. return OBS_OUTPUT_ERROR;
  906. }
  907. stream->socket_thread_active = true;
  908. stream->rtmp.m_bCustomSend = true;
  909. stream->rtmp.m_customSendFunc = socket_queue_data;
  910. stream->rtmp.m_customSendParam = stream;
  911. #endif
  912. }
  913. os_atomic_set_bool(&stream->active, true);
  914. if (!send_meta_data(stream)) {
  915. warn("Disconnected while attempting to send metadata");
  916. set_output_error(stream);
  917. return OBS_OUTPUT_DISCONNECTED;
  918. }
  919. obs_encoder_t *aencoder = obs_output_get_audio_encoder(context, 1);
  920. if (aencoder && !send_additional_meta_data(stream)) {
  921. warn("Disconnected while attempting to send additional "
  922. "metadata");
  923. return OBS_OUTPUT_DISCONNECTED;
  924. }
  925. if (obs_output_get_audio_encoder(context, 2) != NULL) {
  926. warn("Additional audio streams not supported");
  927. return OBS_OUTPUT_DISCONNECTED;
  928. }
  929. obs_output_begin_data_capture(stream->output, 0);
  930. return OBS_OUTPUT_SUCCESS;
  931. }
  932. #ifdef _WIN32
  933. static void win32_log_interface_type(struct rtmp_stream *stream)
  934. {
  935. RTMP *rtmp = &stream->rtmp;
  936. MIB_IPFORWARDROW route;
  937. uint32_t dest_addr, source_addr;
  938. char hostname[256];
  939. HOSTENT *h;
  940. if (rtmp->Link.hostname.av_len >= sizeof(hostname) - 1)
  941. return;
  942. strncpy(hostname, rtmp->Link.hostname.av_val, sizeof(hostname));
  943. hostname[rtmp->Link.hostname.av_len] = 0;
  944. h = gethostbyname(hostname);
  945. if (!h)
  946. return;
  947. dest_addr = *(uint32_t *)h->h_addr_list[0];
  948. if (rtmp->m_bindIP.addrLen == 0)
  949. source_addr = 0;
  950. else if (rtmp->m_bindIP.addr.ss_family == AF_INET)
  951. source_addr = (*(struct sockaddr_in *)&rtmp->m_bindIP.addr)
  952. .sin_addr.S_un.S_addr;
  953. else
  954. return;
  955. if (!GetBestRoute(dest_addr, source_addr, &route)) {
  956. MIB_IF_ROW2 row;
  957. memset(&row, 0, sizeof(row));
  958. row.InterfaceIndex = route.dwForwardIfIndex;
  959. if (!GetIfEntry2(&row)) {
  960. uint32_t rxSpeed = row.ReceiveLinkSpeed / 1000000;
  961. uint32_t txSpeed = row.TransmitLinkSpeed / 1000000;
  962. char *type;
  963. struct dstr other = {0};
  964. switch (row.PhysicalMediumType) {
  965. case NdisPhysicalMedium802_3:
  966. type = "ethernet";
  967. break;
  968. case NdisPhysicalMediumWirelessLan:
  969. case NdisPhysicalMediumNative802_11:
  970. type = "802.11";
  971. break;
  972. default:
  973. dstr_printf(&other, "type %d",
  974. (int)row.PhysicalMediumType);
  975. type = other.array;
  976. break;
  977. }
  978. char *desc;
  979. os_wcs_to_utf8_ptr(row.Description, 0, &desc);
  980. info("Interface: %s (%s, %lu↓/%lu↑ mbps)", desc, type,
  981. rxSpeed, txSpeed);
  982. bfree(desc);
  983. if (row.InErrors || row.OutErrors) {
  984. warn("Interface has non-zero error counters (%" PRIu64
  985. "/%" PRIu64 " errors, %" PRIu64 "/%" PRIu64
  986. " discards)",
  987. row.InErrors, row.OutErrors,
  988. row.InDiscards, row.OutDiscards);
  989. }
  990. dstr_free(&other);
  991. }
  992. }
  993. }
  994. #endif
  995. static int try_connect(struct rtmp_stream *stream)
  996. {
  997. if (dstr_is_empty(&stream->path)) {
  998. warn("URL is empty");
  999. return OBS_OUTPUT_BAD_PATH;
  1000. }
  1001. info("Connecting to RTMP URL %s...", stream->path.array);
  1002. // free any existing RTMP TLS context
  1003. RTMP_TLS_Free(&stream->rtmp);
  1004. RTMP_Init(&stream->rtmp);
  1005. if (!RTMP_SetupURL(&stream->rtmp, stream->path.array))
  1006. return OBS_OUTPUT_BAD_PATH;
  1007. RTMP_EnableWrite(&stream->rtmp);
  1008. dstr_copy(&stream->encoder_name, "FMLE/3.0 (compatible; FMSc/1.0)");
  1009. set_rtmp_dstr(&stream->rtmp.Link.pubUser, &stream->username);
  1010. set_rtmp_dstr(&stream->rtmp.Link.pubPasswd, &stream->password);
  1011. set_rtmp_dstr(&stream->rtmp.Link.flashVer, &stream->encoder_name);
  1012. stream->rtmp.Link.swfUrl = stream->rtmp.Link.tcUrl;
  1013. if (dstr_is_empty(&stream->bind_ip) ||
  1014. dstr_cmp(&stream->bind_ip, "default") == 0) {
  1015. memset(&stream->rtmp.m_bindIP, 0,
  1016. sizeof(stream->rtmp.m_bindIP));
  1017. } else {
  1018. bool success = netif_str_to_addr(&stream->rtmp.m_bindIP.addr,
  1019. &stream->rtmp.m_bindIP.addrLen,
  1020. stream->bind_ip.array);
  1021. if (success) {
  1022. int len = stream->rtmp.m_bindIP.addrLen;
  1023. bool ipv6 = len == sizeof(struct sockaddr_in6);
  1024. info("Binding to IPv%d", ipv6 ? 6 : 4);
  1025. }
  1026. }
  1027. // Only use the IPv4 / IPv6 hint if a binding address isn't specified.
  1028. if (stream->rtmp.m_bindIP.addrLen == 0)
  1029. stream->rtmp.m_bindIP.addrLen = stream->addrlen_hint;
  1030. RTMP_AddStream(&stream->rtmp, stream->key.array);
  1031. stream->rtmp.m_outChunkSize = 4096;
  1032. stream->rtmp.m_bSendChunkSizeInfo = true;
  1033. stream->rtmp.m_bUseNagle = true;
  1034. #ifdef _WIN32
  1035. win32_log_interface_type(stream);
  1036. #endif
  1037. if (!RTMP_Connect(&stream->rtmp, NULL)) {
  1038. set_output_error(stream);
  1039. return OBS_OUTPUT_CONNECT_FAILED;
  1040. }
  1041. if (!RTMP_ConnectStream(&stream->rtmp, 0))
  1042. return OBS_OUTPUT_INVALID_STREAM;
  1043. char ip_address[INET6_ADDRSTRLEN] = {0};
  1044. netif_addr_to_str(&stream->rtmp.m_sb.sb_addr, ip_address,
  1045. INET6_ADDRSTRLEN);
  1046. info("Connection to %s (%s) successful", stream->path.array,
  1047. ip_address);
  1048. return init_send(stream);
  1049. }
  1050. static bool init_connect(struct rtmp_stream *stream)
  1051. {
  1052. obs_service_t *service;
  1053. obs_data_t *settings;
  1054. const char *bind_ip;
  1055. const char *ip_family;
  1056. int64_t drop_p;
  1057. int64_t drop_b;
  1058. uint32_t caps;
  1059. if (stopping(stream)) {
  1060. pthread_join(stream->send_thread, NULL);
  1061. }
  1062. free_packets(stream);
  1063. service = obs_output_get_service(stream->output);
  1064. if (!service)
  1065. return false;
  1066. os_atomic_set_bool(&stream->disconnected, false);
  1067. os_atomic_set_bool(&stream->encode_error, false);
  1068. stream->total_bytes_sent = 0;
  1069. stream->dropped_frames = 0;
  1070. stream->min_priority = 0;
  1071. stream->got_first_video = false;
  1072. settings = obs_output_get_settings(stream->output);
  1073. dstr_copy(&stream->path,
  1074. obs_service_get_connect_info(
  1075. service, OBS_SERVICE_CONNECT_INFO_SERVER_URL));
  1076. dstr_copy(&stream->key,
  1077. obs_service_get_connect_info(
  1078. service, OBS_SERVICE_CONNECT_INFO_STREAM_KEY));
  1079. dstr_copy(&stream->username,
  1080. obs_service_get_connect_info(
  1081. service, OBS_SERVICE_CONNECT_INFO_USERNAME));
  1082. dstr_copy(&stream->password,
  1083. obs_service_get_connect_info(
  1084. service, OBS_SERVICE_CONNECT_INFO_PASSWORD));
  1085. dstr_depad(&stream->path);
  1086. dstr_depad(&stream->key);
  1087. drop_b = (int64_t)obs_data_get_int(settings, OPT_DROP_THRESHOLD);
  1088. drop_p = (int64_t)obs_data_get_int(settings, OPT_PFRAME_DROP_THRESHOLD);
  1089. stream->max_shutdown_time_sec =
  1090. (int)obs_data_get_int(settings, OPT_MAX_SHUTDOWN_TIME_SEC);
  1091. obs_encoder_t *venc = obs_output_get_video_encoder(stream->output);
  1092. obs_encoder_t *aenc = obs_output_get_audio_encoder(stream->output, 0);
  1093. obs_data_t *vsettings = obs_encoder_get_settings(venc);
  1094. obs_data_t *asettings = obs_encoder_get_settings(aenc);
  1095. for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) {
  1096. obs_encoder_t *enc =
  1097. obs_output_get_video_encoder2(stream->output, i);
  1098. if (enc) {
  1099. const char *codec = obs_encoder_get_codec(enc);
  1100. stream->video_codec[i] = to_video_type(codec);
  1101. }
  1102. }
  1103. deque_free(&stream->dbr_frames);
  1104. stream->audio_bitrate = (long)obs_data_get_int(asettings, "bitrate");
  1105. stream->dbr_data_size = 0;
  1106. stream->dbr_orig_bitrate = (long)obs_data_get_int(vsettings, "bitrate");
  1107. stream->dbr_cur_bitrate = stream->dbr_orig_bitrate;
  1108. stream->dbr_est_bitrate = 0;
  1109. stream->dbr_inc_bitrate = stream->dbr_orig_bitrate / 10;
  1110. stream->dbr_inc_timeout = 0;
  1111. stream->dbr_enabled = obs_data_get_bool(settings, OPT_DYN_BITRATE);
  1112. caps = obs_encoder_get_caps(venc);
  1113. if ((caps & OBS_ENCODER_CAP_DYN_BITRATE) == 0) {
  1114. stream->dbr_enabled = false;
  1115. info("Dynamic bitrate disabled. "
  1116. "The encoder does not support on-the-fly bitrate reconfiguration.");
  1117. }
  1118. if (obs_output_get_delay(stream->output) != 0) {
  1119. stream->dbr_enabled = false;
  1120. }
  1121. if (stream->dbr_enabled) {
  1122. info("Dynamic bitrate enabled. Dropped frames begone!");
  1123. }
  1124. obs_data_release(vsettings);
  1125. obs_data_release(asettings);
  1126. if (drop_p < (drop_b + 200))
  1127. drop_p = drop_b + 200;
  1128. stream->drop_threshold_usec = 1000 * drop_b;
  1129. stream->pframe_drop_threshold_usec = 1000 * drop_p;
  1130. bind_ip = obs_data_get_string(settings, OPT_BIND_IP);
  1131. dstr_copy(&stream->bind_ip, bind_ip);
  1132. // Check that we have an IP Family set and that the setting length
  1133. // is 4 characters long so we don't capture ie. IPv4+IPv6
  1134. ip_family = obs_data_get_string(settings, OPT_IP_FAMILY);
  1135. if (ip_family != NULL && strlen(ip_family) == 4) {
  1136. socklen_t len = 0;
  1137. if (strncmp(ip_family, "IPv6", 4) == 0)
  1138. len = sizeof(struct sockaddr_in6);
  1139. else if (strncmp(ip_family, "IPv4", 4) == 0)
  1140. len = sizeof(struct sockaddr_in);
  1141. stream->addrlen_hint = len;
  1142. }
  1143. #ifdef _WIN32
  1144. stream->new_socket_loop =
  1145. obs_data_get_bool(settings, OPT_NEWSOCKETLOOP_ENABLED);
  1146. stream->low_latency_mode =
  1147. obs_data_get_bool(settings, OPT_LOWLATENCY_ENABLED);
  1148. // ugly hack for now, can be removed once new loop is reworked
  1149. if (stream->new_socket_loop &&
  1150. !strncmp(stream->path.array, "rtmps://", 8)) {
  1151. warn("Disabling network optimizations, not compatible with RTMPS");
  1152. stream->new_socket_loop = false;
  1153. }
  1154. #else
  1155. stream->new_socket_loop = false;
  1156. stream->low_latency_mode = false;
  1157. #endif
  1158. obs_data_release(settings);
  1159. return true;
  1160. }
  1161. static void *connect_thread(void *data)
  1162. {
  1163. struct rtmp_stream *stream = data;
  1164. int ret;
  1165. os_set_thread_name("rtmp-stream: connect_thread");
  1166. if (!init_connect(stream)) {
  1167. obs_output_signal_stop(stream->output, OBS_OUTPUT_BAD_PATH);
  1168. return NULL;
  1169. }
  1170. // HDR streaming disabled for AV1
  1171. for (size_t i = 0; i < MAX_OUTPUT_VIDEO_ENCODERS; i++) {
  1172. if (stream->video_codec[i] &&
  1173. stream->video_codec[i] != CODEC_H264 &&
  1174. stream->video_codec[i] != CODEC_HEVC) {
  1175. video_t *video = obs_get_video();
  1176. const struct video_output_info *info =
  1177. video_output_get_info(video);
  1178. if (info->colorspace == VIDEO_CS_2100_HLG ||
  1179. info->colorspace == VIDEO_CS_2100_PQ) {
  1180. obs_output_signal_stop(stream->output,
  1181. OBS_OUTPUT_HDR_DISABLED);
  1182. return NULL;
  1183. }
  1184. }
  1185. }
  1186. ret = try_connect(stream);
  1187. if (ret != OBS_OUTPUT_SUCCESS) {
  1188. obs_output_signal_stop(stream->output, ret);
  1189. info("Connection to %s failed: %d", stream->path.array, ret);
  1190. }
  1191. if (!stopping(stream))
  1192. pthread_detach(stream->connect_thread);
  1193. os_atomic_set_bool(&stream->connecting, false);
  1194. return NULL;
  1195. }
  1196. static bool rtmp_stream_start(void *data)
  1197. {
  1198. struct rtmp_stream *stream = data;
  1199. if (!obs_output_can_begin_data_capture(stream->output, 0))
  1200. return false;
  1201. if (!obs_output_initialize_encoders(stream->output, 0))
  1202. return false;
  1203. os_atomic_set_bool(&stream->connecting, true);
  1204. return pthread_create(&stream->connect_thread, NULL, connect_thread,
  1205. stream) == 0;
  1206. }
  1207. static inline bool add_packet(struct rtmp_stream *stream,
  1208. struct encoder_packet *packet)
  1209. {
  1210. deque_push_back(&stream->packets, packet,
  1211. sizeof(struct encoder_packet));
  1212. return true;
  1213. }
  1214. static inline size_t num_buffered_packets(struct rtmp_stream *stream)
  1215. {
  1216. return stream->packets.size / sizeof(struct encoder_packet);
  1217. }
  1218. static void drop_frames(struct rtmp_stream *stream, const char *name,
  1219. int highest_priority, bool pframes)
  1220. {
  1221. UNUSED_PARAMETER(pframes);
  1222. struct deque new_buf = {0};
  1223. int num_frames_dropped = 0;
  1224. #ifdef _DEBUG
  1225. int start_packets = (int)num_buffered_packets(stream);
  1226. #else
  1227. UNUSED_PARAMETER(name);
  1228. #endif
  1229. deque_reserve(&new_buf, sizeof(struct encoder_packet) * 8);
  1230. while (stream->packets.size) {
  1231. struct encoder_packet packet;
  1232. deque_pop_front(&stream->packets, &packet, sizeof(packet));
  1233. /* do not drop audio data or video keyframes */
  1234. if (packet.type == OBS_ENCODER_AUDIO ||
  1235. packet.drop_priority >= highest_priority) {
  1236. deque_push_back(&new_buf, &packet, sizeof(packet));
  1237. } else {
  1238. num_frames_dropped++;
  1239. obs_encoder_packet_release(&packet);
  1240. }
  1241. }
  1242. deque_free(&stream->packets);
  1243. stream->packets = new_buf;
  1244. if (stream->min_priority < highest_priority)
  1245. stream->min_priority = highest_priority;
  1246. if (!num_frames_dropped)
  1247. return;
  1248. stream->dropped_frames += num_frames_dropped;
  1249. #ifdef _DEBUG
  1250. debug("Dropped %s, prev packet count: %d, new packet count: %d", name,
  1251. start_packets, (int)num_buffered_packets(stream));
  1252. #endif
  1253. }
  1254. static bool find_first_video_packet(struct rtmp_stream *stream,
  1255. struct encoder_packet *first)
  1256. {
  1257. size_t count = stream->packets.size / sizeof(*first);
  1258. for (size_t i = 0; i < count; i++) {
  1259. struct encoder_packet *cur =
  1260. deque_data(&stream->packets, i * sizeof(*first));
  1261. if (cur->type == OBS_ENCODER_VIDEO && !cur->keyframe) {
  1262. *first = *cur;
  1263. return true;
  1264. }
  1265. }
  1266. return false;
  1267. }
  1268. static bool dbr_bitrate_lowered(struct rtmp_stream *stream)
  1269. {
  1270. long prev_bitrate = stream->dbr_prev_bitrate;
  1271. long est_bitrate = 0;
  1272. long new_bitrate;
  1273. if (stream->dbr_est_bitrate &&
  1274. stream->dbr_est_bitrate < stream->dbr_cur_bitrate) {
  1275. stream->dbr_data_size = 0;
  1276. deque_pop_front(&stream->dbr_frames, NULL,
  1277. stream->dbr_frames.size);
  1278. est_bitrate = stream->dbr_est_bitrate / 100 * 100;
  1279. if (est_bitrate < 50) {
  1280. est_bitrate = 50;
  1281. }
  1282. }
  1283. #if 0
  1284. if (prev_bitrate && est_bitrate) {
  1285. if (prev_bitrate < est_bitrate) {
  1286. blog(LOG_INFO, "going back to prev bitrate: "
  1287. "prev_bitrate (%d) < est_bitrate (%d)",
  1288. prev_bitrate,
  1289. est_bitrate);
  1290. new_bitrate = prev_bitrate;
  1291. } else {
  1292. new_bitrate = est_bitrate;
  1293. }
  1294. new_bitrate = est_bitrate;
  1295. } else if (prev_bitrate) {
  1296. new_bitrate = prev_bitrate;
  1297. info("going back to prev bitrate");
  1298. } else if (est_bitrate) {
  1299. new_bitrate = est_bitrate;
  1300. } else {
  1301. return false;
  1302. }
  1303. #else
  1304. if (est_bitrate) {
  1305. new_bitrate = est_bitrate;
  1306. } else if (prev_bitrate) {
  1307. new_bitrate = prev_bitrate;
  1308. info("going back to prev bitrate");
  1309. } else {
  1310. return false;
  1311. }
  1312. if (new_bitrate == stream->dbr_cur_bitrate) {
  1313. return false;
  1314. }
  1315. #endif
  1316. stream->dbr_prev_bitrate = 0;
  1317. stream->dbr_cur_bitrate = new_bitrate;
  1318. stream->dbr_inc_timeout = os_gettime_ns() + DBR_INC_TIMER;
  1319. info("bitrate decreased to: %ld", stream->dbr_cur_bitrate);
  1320. return true;
  1321. }
  1322. static void dbr_set_bitrate(struct rtmp_stream *stream)
  1323. {
  1324. obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
  1325. obs_data_t *settings = obs_encoder_get_settings(vencoder);
  1326. obs_data_set_int(settings, "bitrate", stream->dbr_cur_bitrate);
  1327. obs_encoder_update(vencoder, settings);
  1328. obs_data_release(settings);
  1329. }
  1330. static void dbr_inc_bitrate(struct rtmp_stream *stream)
  1331. {
  1332. stream->dbr_prev_bitrate = stream->dbr_cur_bitrate;
  1333. stream->dbr_cur_bitrate += stream->dbr_inc_bitrate;
  1334. if (stream->dbr_cur_bitrate >= stream->dbr_orig_bitrate) {
  1335. stream->dbr_cur_bitrate = stream->dbr_orig_bitrate;
  1336. info("bitrate increased to: %ld, done",
  1337. stream->dbr_cur_bitrate);
  1338. } else if (stream->dbr_cur_bitrate < stream->dbr_orig_bitrate) {
  1339. stream->dbr_inc_timeout = os_gettime_ns() + DBR_INC_TIMER;
  1340. info("bitrate increased to: %ld, waiting",
  1341. stream->dbr_cur_bitrate);
  1342. }
  1343. }
  1344. static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes)
  1345. {
  1346. struct encoder_packet first;
  1347. int64_t buffer_duration_usec;
  1348. size_t num_packets = num_buffered_packets(stream);
  1349. const char *name = pframes ? "p-frames" : "b-frames";
  1350. int priority = pframes ? OBS_NAL_PRIORITY_HIGHEST
  1351. : OBS_NAL_PRIORITY_HIGH;
  1352. int64_t drop_threshold = pframes ? stream->pframe_drop_threshold_usec
  1353. : stream->drop_threshold_usec;
  1354. if (!pframes && stream->dbr_enabled) {
  1355. if (stream->dbr_inc_timeout) {
  1356. uint64_t t = os_gettime_ns();
  1357. if (t >= stream->dbr_inc_timeout) {
  1358. stream->dbr_inc_timeout = 0;
  1359. dbr_inc_bitrate(stream);
  1360. dbr_set_bitrate(stream);
  1361. }
  1362. }
  1363. }
  1364. if (num_packets < 5) {
  1365. if (!pframes)
  1366. stream->congestion = 0.0f;
  1367. return;
  1368. }
  1369. if (!find_first_video_packet(stream, &first))
  1370. return;
  1371. /* if the amount of time stored in the buffered packets waiting to be
  1372. * sent is higher than threshold, drop frames */
  1373. buffer_duration_usec = stream->last_dts_usec - first.dts_usec;
  1374. if (!pframes) {
  1375. stream->congestion =
  1376. (float)buffer_duration_usec / (float)drop_threshold;
  1377. }
  1378. /* alternatively, drop only pframes:
  1379. * (!pframes && stream->dbr_enabled)
  1380. * but let's test without dropping frames
  1381. * at all first */
  1382. if (stream->dbr_enabled) {
  1383. bool bitrate_changed = false;
  1384. if (pframes) {
  1385. return;
  1386. }
  1387. if ((uint64_t)buffer_duration_usec >= DBR_TRIGGER_USEC) {
  1388. pthread_mutex_lock(&stream->dbr_mutex);
  1389. bitrate_changed = dbr_bitrate_lowered(stream);
  1390. pthread_mutex_unlock(&stream->dbr_mutex);
  1391. }
  1392. if (bitrate_changed) {
  1393. debug("buffer_duration_msec: %" PRId64,
  1394. buffer_duration_usec / 1000);
  1395. dbr_set_bitrate(stream);
  1396. }
  1397. return;
  1398. }
  1399. if (buffer_duration_usec > drop_threshold) {
  1400. debug("buffer_duration_usec: %" PRId64, buffer_duration_usec);
  1401. drop_frames(stream, name, priority, pframes);
  1402. }
  1403. }
  1404. static bool add_video_packet(struct rtmp_stream *stream,
  1405. struct encoder_packet *packet)
  1406. {
  1407. check_to_drop_frames(stream, false);
  1408. check_to_drop_frames(stream, true);
  1409. /* if currently dropping frames, drop packets until it reaches the
  1410. * desired priority */
  1411. if (packet->drop_priority < stream->min_priority) {
  1412. stream->dropped_frames++;
  1413. return false;
  1414. } else {
  1415. stream->min_priority = 0;
  1416. }
  1417. stream->last_dts_usec = packet->dts_usec;
  1418. return add_packet(stream, packet);
  1419. }
  1420. static void rtmp_stream_data(void *data, struct encoder_packet *packet)
  1421. {
  1422. struct rtmp_stream *stream = data;
  1423. struct encoder_packet new_packet;
  1424. bool added_packet = false;
  1425. if (disconnected(stream) || !active(stream))
  1426. return;
  1427. /* encoder fail */
  1428. if (!packet) {
  1429. os_atomic_set_bool(&stream->encode_error, true);
  1430. os_sem_post(stream->send_sem);
  1431. return;
  1432. }
  1433. if (packet->type == OBS_ENCODER_VIDEO) {
  1434. if (!stream->got_first_video) {
  1435. stream->start_dts_offset =
  1436. get_ms_time(packet, packet->dts);
  1437. stream->got_first_video = true;
  1438. }
  1439. switch (stream->video_codec[packet->track_idx]) {
  1440. case CODEC_H264:
  1441. obs_parse_avc_packet(&new_packet, packet);
  1442. break;
  1443. case CODEC_HEVC:
  1444. #ifdef ENABLE_HEVC
  1445. obs_parse_hevc_packet(&new_packet, packet);
  1446. break;
  1447. #else
  1448. return;
  1449. #endif
  1450. case CODEC_AV1:
  1451. obs_parse_av1_packet(&new_packet, packet);
  1452. break;
  1453. }
  1454. } else {
  1455. obs_encoder_packet_ref(&new_packet, packet);
  1456. }
  1457. pthread_mutex_lock(&stream->packets_mutex);
  1458. if (!disconnected(stream)) {
  1459. added_packet = (packet->type == OBS_ENCODER_VIDEO)
  1460. ? add_video_packet(stream, &new_packet)
  1461. : add_packet(stream, &new_packet);
  1462. }
  1463. pthread_mutex_unlock(&stream->packets_mutex);
  1464. if (added_packet)
  1465. os_sem_post(stream->send_sem);
  1466. else
  1467. obs_encoder_packet_release(&new_packet);
  1468. }
  1469. static void rtmp_stream_defaults(obs_data_t *defaults)
  1470. {
  1471. obs_data_set_default_int(defaults, OPT_DROP_THRESHOLD, 700);
  1472. obs_data_set_default_int(defaults, OPT_PFRAME_DROP_THRESHOLD, 900);
  1473. obs_data_set_default_int(defaults, OPT_MAX_SHUTDOWN_TIME_SEC, 30);
  1474. obs_data_set_default_string(defaults, OPT_BIND_IP, "default");
  1475. #ifdef _WIN32
  1476. obs_data_set_default_bool(defaults, OPT_NEWSOCKETLOOP_ENABLED, false);
  1477. obs_data_set_default_bool(defaults, OPT_LOWLATENCY_ENABLED, false);
  1478. #endif
  1479. }
  1480. static obs_properties_t *rtmp_stream_properties(void *unused)
  1481. {
  1482. UNUSED_PARAMETER(unused);
  1483. obs_properties_t *props = obs_properties_create();
  1484. struct netif_saddr_data addrs = {0};
  1485. obs_property_t *p;
  1486. p = obs_properties_add_int(props, OPT_DROP_THRESHOLD,
  1487. obs_module_text("RTMPStream.DropThreshold"),
  1488. 200, 10000, 100);
  1489. obs_property_int_set_suffix(p, " ms");
  1490. p = obs_properties_add_list(props, OPT_IP_FAMILY,
  1491. obs_module_text("IPFamily"),
  1492. OBS_COMBO_TYPE_LIST,
  1493. OBS_COMBO_FORMAT_STRING);
  1494. obs_property_list_add_string(p, obs_module_text("IPFamily.Both"),
  1495. "IPv4+IPv6");
  1496. obs_property_list_add_string(p, obs_module_text("IPFamily.V4Only"),
  1497. "IPv4");
  1498. obs_property_list_add_string(p, obs_module_text("IPFamily.V6Only"),
  1499. "IPv6");
  1500. p = obs_properties_add_list(props, OPT_BIND_IP,
  1501. obs_module_text("RTMPStream.BindIP"),
  1502. OBS_COMBO_TYPE_LIST,
  1503. OBS_COMBO_FORMAT_STRING);
  1504. obs_property_list_add_string(p, obs_module_text("Default"), "default");
  1505. netif_get_addrs(&addrs);
  1506. for (size_t i = 0; i < addrs.addrs.num; i++) {
  1507. struct netif_saddr_item item = addrs.addrs.array[i];
  1508. obs_property_list_add_string(p, item.name, item.addr);
  1509. }
  1510. netif_saddr_data_free(&addrs);
  1511. #ifdef _WIN32
  1512. obs_properties_add_bool(props, OPT_NEWSOCKETLOOP_ENABLED,
  1513. obs_module_text("RTMPStream.NewSocketLoop"));
  1514. obs_properties_add_bool(props, OPT_LOWLATENCY_ENABLED,
  1515. obs_module_text("RTMPStream.LowLatencyMode"));
  1516. #endif
  1517. return props;
  1518. }
  1519. static uint64_t rtmp_stream_total_bytes_sent(void *data)
  1520. {
  1521. struct rtmp_stream *stream = data;
  1522. return stream->total_bytes_sent;
  1523. }
  1524. static int rtmp_stream_dropped_frames(void *data)
  1525. {
  1526. struct rtmp_stream *stream = data;
  1527. return stream->dropped_frames;
  1528. }
  1529. static float rtmp_stream_congestion(void *data)
  1530. {
  1531. struct rtmp_stream *stream = data;
  1532. if (stream->new_socket_loop)
  1533. return (float)stream->write_buf_len /
  1534. (float)stream->write_buf_size;
  1535. else
  1536. return stream->min_priority > 0 ? 1.0f : stream->congestion;
  1537. }
  1538. static int rtmp_stream_connect_time(void *data)
  1539. {
  1540. struct rtmp_stream *stream = data;
  1541. return stream->rtmp.connect_time_ms;
  1542. }
  1543. struct obs_output_info rtmp_output_info = {
  1544. .id = "rtmp_output",
  1545. .flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED | OBS_OUTPUT_SERVICE |
  1546. OBS_OUTPUT_MULTI_TRACK_AV,
  1547. #ifdef NO_CRYPTO
  1548. .protocols = "RTMP",
  1549. #else
  1550. .protocols = "RTMP;RTMPS",
  1551. #endif
  1552. #ifdef ENABLE_HEVC
  1553. .encoded_video_codecs = "h264;hevc;av1",
  1554. #else
  1555. .encoded_video_codecs = "h264;av1",
  1556. #endif
  1557. .encoded_audio_codecs = "aac",
  1558. .get_name = rtmp_stream_getname,
  1559. .create = rtmp_stream_create,
  1560. .destroy = rtmp_stream_destroy,
  1561. .start = rtmp_stream_start,
  1562. .stop = rtmp_stream_stop,
  1563. .encoded_packet = rtmp_stream_data,
  1564. .get_defaults = rtmp_stream_defaults,
  1565. .get_properties = rtmp_stream_properties,
  1566. .get_total_bytes = rtmp_stream_total_bytes_sent,
  1567. .get_congestion = rtmp_stream_congestion,
  1568. .get_connect_time_ms = rtmp_stream_connect_time,
  1569. .get_dropped_frames = rtmp_stream_dropped_frames,
  1570. };