obs-ffmpeg-mux.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. /******************************************************************************
  2. Copyright (C) 2015 by Hugh 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 "ffmpeg-mux/ffmpeg-mux.h"
  15. #include "obs-ffmpeg-mux.h"
  16. #ifdef _WIN32
  17. #include "util/windows/win-version.h"
  18. #endif
  19. #include <libavformat/avformat.h>
  20. #define do_log(level, format, ...) \
  21. blog(level, "[ffmpeg muxer: '%s'] " format, \
  22. obs_output_get_name(stream->output), ##__VA_ARGS__)
  23. #define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
  24. #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
  25. static const char *ffmpeg_mux_getname(void *type)
  26. {
  27. UNUSED_PARAMETER(type);
  28. return obs_module_text("FFmpegMuxer");
  29. }
  30. #ifndef NEW_MPEGTS_OUTPUT
  31. static const char *ffmpeg_mpegts_mux_getname(void *type)
  32. {
  33. UNUSED_PARAMETER(type);
  34. return obs_module_text("FFmpegMpegtsMuxer");
  35. }
  36. #endif
  37. static inline void replay_buffer_clear(struct ffmpeg_muxer *stream)
  38. {
  39. while (stream->packets.size > 0) {
  40. struct encoder_packet pkt;
  41. circlebuf_pop_front(&stream->packets, &pkt, sizeof(pkt));
  42. obs_encoder_packet_release(&pkt);
  43. }
  44. circlebuf_free(&stream->packets);
  45. stream->cur_size = 0;
  46. stream->cur_time = 0;
  47. stream->max_size = 0;
  48. stream->max_time = 0;
  49. stream->save_ts = 0;
  50. stream->keyframes = 0;
  51. }
  52. static void ffmpeg_mux_destroy(void *data)
  53. {
  54. struct ffmpeg_muxer *stream = data;
  55. replay_buffer_clear(stream);
  56. if (stream->mux_thread_joinable)
  57. pthread_join(stream->mux_thread, NULL);
  58. for (size_t i = 0; i < stream->mux_packets.num; i++)
  59. obs_encoder_packet_release(&stream->mux_packets.array[i]);
  60. da_free(stream->mux_packets);
  61. circlebuf_free(&stream->packets);
  62. os_process_pipe_destroy(stream->pipe);
  63. dstr_free(&stream->path);
  64. dstr_free(&stream->printable_path);
  65. dstr_free(&stream->stream_key);
  66. dstr_free(&stream->muxer_settings);
  67. bfree(stream);
  68. }
  69. static void split_file_proc(void *data, calldata_t *cd)
  70. {
  71. struct ffmpeg_muxer *stream = data;
  72. calldata_set_bool(cd, "split_file_enabled", stream->split_file);
  73. if (!stream->split_file)
  74. return;
  75. os_atomic_set_bool(&stream->manual_split, true);
  76. }
  77. static void *ffmpeg_mux_create(obs_data_t *settings, obs_output_t *output)
  78. {
  79. struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream));
  80. stream->output = output;
  81. if (obs_output_get_flags(output) & OBS_OUTPUT_SERVICE)
  82. stream->is_network = true;
  83. signal_handler_t *sh = obs_output_get_signal_handler(output);
  84. signal_handler_add(sh, "void file_changed(string next_file)");
  85. proc_handler_t *ph = obs_output_get_proc_handler(output);
  86. proc_handler_add(ph, "void split_file(out bool split_file_enabled)",
  87. split_file_proc, stream);
  88. UNUSED_PARAMETER(settings);
  89. return stream;
  90. }
  91. #ifdef _WIN32
  92. #define FFMPEG_MUX "obs-ffmpeg-mux.exe"
  93. #else
  94. #define FFMPEG_MUX "obs-ffmpeg-mux"
  95. #endif
  96. static inline bool capturing(struct ffmpeg_muxer *stream)
  97. {
  98. return os_atomic_load_bool(&stream->capturing);
  99. }
  100. bool stopping(struct ffmpeg_muxer *stream)
  101. {
  102. return os_atomic_load_bool(&stream->stopping);
  103. }
  104. bool active(struct ffmpeg_muxer *stream)
  105. {
  106. return os_atomic_load_bool(&stream->active);
  107. }
  108. /* TODO: allow codecs other than h264 whenever we start using them */
  109. static void add_video_encoder_params(struct ffmpeg_muxer *stream,
  110. struct dstr *cmd, obs_encoder_t *vencoder)
  111. {
  112. obs_data_t *settings = obs_encoder_get_settings(vencoder);
  113. int bitrate = (int)obs_data_get_int(settings, "bitrate");
  114. video_t *video = obs_get_video();
  115. const struct video_output_info *info = video_output_get_info(video);
  116. obs_data_release(settings);
  117. enum AVColorPrimaries pri = AVCOL_PRI_UNSPECIFIED;
  118. enum AVColorTransferCharacteristic trc = AVCOL_TRC_UNSPECIFIED;
  119. enum AVColorSpace spc = AVCOL_SPC_UNSPECIFIED;
  120. switch (info->colorspace) {
  121. case VIDEO_CS_601:
  122. pri = AVCOL_PRI_SMPTE170M;
  123. trc = AVCOL_TRC_SMPTE170M;
  124. spc = AVCOL_SPC_SMPTE170M;
  125. break;
  126. case VIDEO_CS_DEFAULT:
  127. case VIDEO_CS_709:
  128. pri = AVCOL_PRI_BT709;
  129. trc = AVCOL_TRC_BT709;
  130. spc = AVCOL_SPC_BT709;
  131. break;
  132. case VIDEO_CS_SRGB:
  133. pri = AVCOL_PRI_BT709;
  134. trc = AVCOL_TRC_IEC61966_2_1;
  135. spc = AVCOL_SPC_BT709;
  136. break;
  137. case VIDEO_CS_2100_PQ:
  138. pri = AVCOL_PRI_BT2020;
  139. trc = AVCOL_TRC_SMPTE2084;
  140. spc = AVCOL_SPC_BT2020_NCL;
  141. break;
  142. case VIDEO_CS_2100_HLG:
  143. pri = AVCOL_PRI_BT2020;
  144. trc = AVCOL_TRC_ARIB_STD_B67;
  145. spc = AVCOL_SPC_BT2020_NCL;
  146. }
  147. const enum AVColorRange range = (info->range == VIDEO_RANGE_FULL)
  148. ? AVCOL_RANGE_JPEG
  149. : AVCOL_RANGE_MPEG;
  150. const int max_luminance =
  151. (trc == AVCOL_TRC_SMPTE2084)
  152. ? (int)obs_get_video_hdr_nominal_peak_level()
  153. : ((trc == AVCOL_TRC_ARIB_STD_B67) ? 1000 : 0);
  154. dstr_catf(cmd, "%s %d %d %d %d %d %d %d %d %d %d ",
  155. obs_encoder_get_codec(vencoder), bitrate,
  156. obs_output_get_width(stream->output),
  157. obs_output_get_height(stream->output), (int)pri, (int)trc,
  158. (int)spc, (int)range, max_luminance, (int)info->fps_num,
  159. (int)info->fps_den);
  160. }
  161. static void add_audio_encoder_params(struct dstr *cmd, obs_encoder_t *aencoder)
  162. {
  163. obs_data_t *settings = obs_encoder_get_settings(aencoder);
  164. int bitrate = (int)obs_data_get_int(settings, "bitrate");
  165. audio_t *audio = obs_get_audio();
  166. struct dstr name = {0};
  167. obs_data_release(settings);
  168. dstr_copy(&name, obs_encoder_get_name(aencoder));
  169. dstr_replace(&name, "\"", "\"\"");
  170. dstr_catf(cmd, "\"%s\" %d %d %d %d ", name.array, bitrate,
  171. (int)obs_encoder_get_sample_rate(aencoder),
  172. (int)obs_encoder_get_frame_size(aencoder),
  173. (int)audio_output_get_channels(audio));
  174. dstr_free(&name);
  175. }
  176. static void log_muxer_params(struct ffmpeg_muxer *stream, const char *settings)
  177. {
  178. int ret;
  179. AVDictionary *dict = NULL;
  180. if ((ret = av_dict_parse_string(&dict, settings, "=", " ", 0))) {
  181. warn("Failed to parse muxer settings: %s\n%s", av_err2str(ret),
  182. settings);
  183. av_dict_free(&dict);
  184. return;
  185. }
  186. if (av_dict_count(dict) > 0) {
  187. struct dstr str = {0};
  188. AVDictionaryEntry *entry = NULL;
  189. while ((entry = av_dict_get(dict, "", entry,
  190. AV_DICT_IGNORE_SUFFIX)))
  191. dstr_catf(&str, "\n\t%s=%s", entry->key, entry->value);
  192. info("Using muxer settings:%s", str.array);
  193. dstr_free(&str);
  194. }
  195. av_dict_free(&dict);
  196. }
  197. static void add_stream_key(struct dstr *cmd, struct ffmpeg_muxer *stream)
  198. {
  199. dstr_catf(cmd, "\"%s\" ",
  200. dstr_is_empty(&stream->stream_key)
  201. ? ""
  202. : stream->stream_key.array);
  203. }
  204. static void add_muxer_params(struct dstr *cmd, struct ffmpeg_muxer *stream)
  205. {
  206. struct dstr mux = {0};
  207. if (dstr_is_empty(&stream->muxer_settings)) {
  208. obs_data_t *settings = obs_output_get_settings(stream->output);
  209. dstr_copy(&mux,
  210. obs_data_get_string(settings, "muxer_settings"));
  211. obs_data_release(settings);
  212. } else {
  213. dstr_copy(&mux, stream->muxer_settings.array);
  214. }
  215. log_muxer_params(stream, mux.array);
  216. dstr_replace(&mux, "\"", "\\\"");
  217. dstr_catf(cmd, "\"%s\" ", mux.array ? mux.array : "");
  218. dstr_free(&mux);
  219. }
  220. static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd,
  221. const char *path)
  222. {
  223. obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
  224. obs_encoder_t *aencoders[MAX_AUDIO_MIXES];
  225. int num_tracks = 0;
  226. for (;;) {
  227. obs_encoder_t *aencoder = obs_output_get_audio_encoder(
  228. stream->output, num_tracks);
  229. if (!aencoder)
  230. break;
  231. aencoders[num_tracks] = aencoder;
  232. num_tracks++;
  233. }
  234. dstr_init_move_array(cmd, os_get_executable_path_ptr(FFMPEG_MUX));
  235. dstr_insert_ch(cmd, 0, '\"');
  236. dstr_cat(cmd, "\" \"");
  237. dstr_copy(&stream->path, path);
  238. dstr_replace(&stream->path, "\"", "\"\"");
  239. dstr_cat_dstr(cmd, &stream->path);
  240. dstr_catf(cmd, "\" %d %d ", vencoder ? 1 : 0, num_tracks);
  241. if (vencoder)
  242. add_video_encoder_params(stream, cmd, vencoder);
  243. if (num_tracks) {
  244. dstr_cat(cmd, "aac ");
  245. for (int i = 0; i < num_tracks; i++) {
  246. add_audio_encoder_params(cmd, aencoders[i]);
  247. }
  248. }
  249. add_stream_key(cmd, stream);
  250. add_muxer_params(cmd, stream);
  251. }
  252. void start_pipe(struct ffmpeg_muxer *stream, const char *path)
  253. {
  254. struct dstr cmd;
  255. build_command_line(stream, &cmd, path);
  256. stream->pipe = os_process_pipe_create(cmd.array, "w");
  257. dstr_free(&cmd);
  258. }
  259. static void set_file_not_readable_error(struct ffmpeg_muxer *stream,
  260. obs_data_t *settings, const char *path)
  261. {
  262. struct dstr error_message;
  263. dstr_init_copy(&error_message, obs_module_text("UnableToWritePath"));
  264. #ifdef _WIN32
  265. /* special warning for Windows 10 users about Defender */
  266. struct win_version_info ver;
  267. get_win_ver(&ver);
  268. if (ver.major >= 10) {
  269. dstr_cat(&error_message, "\n\n");
  270. dstr_cat(&error_message,
  271. obs_module_text("WarnWindowsDefender"));
  272. }
  273. #endif
  274. dstr_replace(&error_message, "%1", path);
  275. obs_output_set_last_error(stream->output, error_message.array);
  276. dstr_free(&error_message);
  277. obs_data_release(settings);
  278. }
  279. inline static void ts_offset_clear(struct ffmpeg_muxer *stream)
  280. {
  281. stream->found_video = false;
  282. stream->video_pts_offset = 0;
  283. for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
  284. stream->found_audio[i] = false;
  285. stream->audio_dts_offsets[i] = 0;
  286. }
  287. }
  288. static inline int64_t packet_pts_usec(struct encoder_packet *packet)
  289. {
  290. return packet->pts * 1000000 / packet->timebase_den;
  291. }
  292. inline static void ts_offset_update(struct ffmpeg_muxer *stream,
  293. struct encoder_packet *packet)
  294. {
  295. if (packet->type == OBS_ENCODER_VIDEO) {
  296. if (!stream->found_video) {
  297. stream->video_pts_offset = packet->pts;
  298. stream->found_video = true;
  299. }
  300. return;
  301. }
  302. if (stream->found_audio[packet->track_idx])
  303. return;
  304. stream->audio_dts_offsets[packet->track_idx] = packet->dts;
  305. stream->found_audio[packet->track_idx] = true;
  306. }
  307. static bool ffmpeg_mux_start(void *data)
  308. {
  309. struct ffmpeg_muxer *stream = data;
  310. obs_data_t *settings;
  311. const char *path;
  312. if (!obs_output_can_begin_data_capture(stream->output, 0))
  313. return false;
  314. if (!obs_output_initialize_encoders(stream->output, 0))
  315. return false;
  316. settings = obs_output_get_settings(stream->output);
  317. if (stream->is_network) {
  318. obs_service_t *service;
  319. service = obs_output_get_service(stream->output);
  320. if (!service)
  321. return false;
  322. path = obs_service_get_url(service);
  323. stream->split_file = false;
  324. } else {
  325. path = obs_data_get_string(settings, "path");
  326. stream->max_time =
  327. obs_data_get_int(settings, "max_time_sec") * 1000000LL;
  328. stream->max_size = obs_data_get_int(settings, "max_size_mb") *
  329. (1024 * 1024);
  330. stream->split_file = obs_data_get_bool(settings, "split_file");
  331. stream->allow_overwrite =
  332. obs_data_get_bool(settings, "allow_overwrite");
  333. stream->cur_size = 0;
  334. stream->sent_headers = false;
  335. }
  336. ts_offset_clear(stream);
  337. if (!stream->is_network) {
  338. /* ensure output path is writable to avoid generic error
  339. * message.
  340. *
  341. * TODO: remove once ffmpeg-mux is refactored to pass
  342. * errors back */
  343. FILE *test_file = os_fopen(path, "wb");
  344. if (!test_file) {
  345. set_file_not_readable_error(stream, settings, path);
  346. return false;
  347. }
  348. fclose(test_file);
  349. os_unlink(path);
  350. }
  351. start_pipe(stream, path);
  352. obs_data_release(settings);
  353. if (!stream->pipe) {
  354. obs_output_set_last_error(
  355. stream->output, obs_module_text("HelperProcessFailed"));
  356. warn("Failed to create process pipe");
  357. return false;
  358. }
  359. /* write headers and start capture */
  360. os_atomic_set_bool(&stream->active, true);
  361. os_atomic_set_bool(&stream->capturing, true);
  362. stream->total_bytes = 0;
  363. obs_output_begin_data_capture(stream->output, 0);
  364. info("Writing file '%s'...", stream->path.array);
  365. return true;
  366. }
  367. int deactivate(struct ffmpeg_muxer *stream, int code)
  368. {
  369. int ret = -1;
  370. if (stream->is_hls) {
  371. if (stream->mux_thread_joinable) {
  372. os_event_signal(stream->stop_event);
  373. os_sem_post(stream->write_sem);
  374. pthread_join(stream->mux_thread, NULL);
  375. stream->mux_thread_joinable = false;
  376. }
  377. }
  378. if (active(stream)) {
  379. ret = os_process_pipe_destroy(stream->pipe);
  380. stream->pipe = NULL;
  381. os_atomic_set_bool(&stream->active, false);
  382. os_atomic_set_bool(&stream->sent_headers, false);
  383. info("Output of file '%s' stopped",
  384. dstr_is_empty(&stream->printable_path)
  385. ? stream->path.array
  386. : stream->printable_path.array);
  387. }
  388. if (code) {
  389. obs_output_signal_stop(stream->output, code);
  390. } else if (stopping(stream)) {
  391. obs_output_end_data_capture(stream->output);
  392. }
  393. if (stream->is_hls) {
  394. pthread_mutex_lock(&stream->write_mutex);
  395. while (stream->packets.size) {
  396. struct encoder_packet packet;
  397. circlebuf_pop_front(&stream->packets, &packet,
  398. sizeof(packet));
  399. obs_encoder_packet_release(&packet);
  400. }
  401. pthread_mutex_unlock(&stream->write_mutex);
  402. }
  403. os_atomic_set_bool(&stream->stopping, false);
  404. return ret;
  405. }
  406. void ffmpeg_mux_stop(void *data, uint64_t ts)
  407. {
  408. struct ffmpeg_muxer *stream = data;
  409. if (capturing(stream) || ts == 0) {
  410. stream->stop_ts = (int64_t)ts / 1000LL;
  411. os_atomic_set_bool(&stream->stopping, true);
  412. os_atomic_set_bool(&stream->capturing, false);
  413. }
  414. }
  415. static void signal_failure(struct ffmpeg_muxer *stream)
  416. {
  417. char error[1024];
  418. int ret;
  419. int code;
  420. size_t len;
  421. len = os_process_pipe_read_err(stream->pipe, (uint8_t *)error,
  422. sizeof(error) - 1);
  423. if (len > 0) {
  424. error[len] = 0;
  425. warn("ffmpeg-mux: %s", error);
  426. obs_output_set_last_error(stream->output, error);
  427. }
  428. ret = deactivate(stream, 0);
  429. switch (ret) {
  430. case FFM_UNSUPPORTED:
  431. code = OBS_OUTPUT_UNSUPPORTED;
  432. break;
  433. default:
  434. if (stream->is_network) {
  435. code = OBS_OUTPUT_DISCONNECTED;
  436. } else {
  437. code = OBS_OUTPUT_ENCODE_ERROR;
  438. }
  439. }
  440. obs_output_signal_stop(stream->output, code);
  441. os_atomic_set_bool(&stream->capturing, false);
  442. }
  443. static void find_best_filename(struct dstr *path, bool space)
  444. {
  445. int num = 2;
  446. if (!os_file_exists(path->array))
  447. return;
  448. const char *ext = strrchr(path->array, '.');
  449. if (!ext)
  450. return;
  451. size_t extstart = ext - path->array;
  452. struct dstr testpath;
  453. dstr_init_copy_dstr(&testpath, path);
  454. for (;;) {
  455. dstr_resize(&testpath, extstart);
  456. dstr_catf(&testpath, space ? " (%d)" : "_%d", num++);
  457. dstr_cat(&testpath, ext);
  458. if (!os_file_exists(testpath.array)) {
  459. dstr_free(path);
  460. dstr_init_move(path, &testpath);
  461. break;
  462. }
  463. }
  464. }
  465. static void generate_filename(struct ffmpeg_muxer *stream, struct dstr *dst,
  466. bool overwrite)
  467. {
  468. obs_data_t *settings = obs_output_get_settings(stream->output);
  469. const char *dir = obs_data_get_string(settings, "directory");
  470. const char *fmt = obs_data_get_string(settings, "format");
  471. const char *ext = obs_data_get_string(settings, "extension");
  472. bool space = obs_data_get_bool(settings, "allow_spaces");
  473. char *filename = os_generate_formatted_filename(ext, space, fmt);
  474. dstr_copy(dst, dir);
  475. dstr_replace(dst, "\\", "/");
  476. if (dstr_end(dst) != '/')
  477. dstr_cat_ch(dst, '/');
  478. dstr_cat(dst, filename);
  479. char *slash = strrchr(dst->array, '/');
  480. if (slash) {
  481. *slash = 0;
  482. os_mkdirs(dst->array);
  483. *slash = '/';
  484. }
  485. if (!overwrite)
  486. find_best_filename(dst, space);
  487. bfree(filename);
  488. obs_data_release(settings);
  489. }
  490. bool write_packet(struct ffmpeg_muxer *stream, struct encoder_packet *packet)
  491. {
  492. bool is_video = packet->type == OBS_ENCODER_VIDEO;
  493. size_t ret;
  494. struct ffm_packet_info info = {.pts = packet->pts,
  495. .dts = packet->dts,
  496. .size = (uint32_t)packet->size,
  497. .index = (int)packet->track_idx,
  498. .type = is_video ? FFM_PACKET_VIDEO
  499. : FFM_PACKET_AUDIO,
  500. .keyframe = packet->keyframe};
  501. if (stream->split_file) {
  502. if (is_video) {
  503. info.dts -= stream->video_pts_offset;
  504. info.pts -= stream->video_pts_offset;
  505. } else {
  506. info.dts -= stream->audio_dts_offsets[info.index];
  507. info.pts -= stream->audio_dts_offsets[info.index];
  508. }
  509. }
  510. ret = os_process_pipe_write(stream->pipe, (const uint8_t *)&info,
  511. sizeof(info));
  512. if (ret != sizeof(info)) {
  513. warn("os_process_pipe_write for info structure failed");
  514. signal_failure(stream);
  515. return false;
  516. }
  517. ret = os_process_pipe_write(stream->pipe, packet->data, packet->size);
  518. if (ret != packet->size) {
  519. warn("os_process_pipe_write for packet data failed");
  520. signal_failure(stream);
  521. return false;
  522. }
  523. stream->total_bytes += packet->size;
  524. if (stream->split_file)
  525. stream->cur_size += packet->size;
  526. return true;
  527. }
  528. static bool send_audio_headers(struct ffmpeg_muxer *stream,
  529. obs_encoder_t *aencoder, size_t idx)
  530. {
  531. struct encoder_packet packet = {
  532. .type = OBS_ENCODER_AUDIO, .timebase_den = 1, .track_idx = idx};
  533. if (!obs_encoder_get_extra_data(aencoder, &packet.data, &packet.size))
  534. return false;
  535. return write_packet(stream, &packet);
  536. }
  537. static bool send_video_headers(struct ffmpeg_muxer *stream)
  538. {
  539. obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
  540. struct encoder_packet packet = {.type = OBS_ENCODER_VIDEO,
  541. .timebase_den = 1};
  542. if (!obs_encoder_get_extra_data(vencoder, &packet.data, &packet.size))
  543. return false;
  544. return write_packet(stream, &packet);
  545. }
  546. bool send_headers(struct ffmpeg_muxer *stream)
  547. {
  548. obs_encoder_t *aencoder;
  549. size_t idx = 0;
  550. if (!send_video_headers(stream))
  551. return false;
  552. do {
  553. aencoder = obs_output_get_audio_encoder(stream->output, idx);
  554. if (aencoder) {
  555. if (!send_audio_headers(stream, aencoder, idx)) {
  556. return false;
  557. }
  558. idx++;
  559. }
  560. } while (aencoder);
  561. return true;
  562. }
  563. static inline bool should_split(struct ffmpeg_muxer *stream,
  564. struct encoder_packet *packet)
  565. {
  566. /* split at video frame */
  567. if (packet->type != OBS_ENCODER_VIDEO)
  568. return false;
  569. /* don't split group of pictures */
  570. if (!packet->keyframe)
  571. return false;
  572. if (os_atomic_load_bool(&stream->manual_split))
  573. return true;
  574. /* reached maximum file size */
  575. if (stream->max_size > 0 &&
  576. stream->cur_size + (int64_t)packet->size >= stream->max_size)
  577. return true;
  578. /* reached maximum duration */
  579. if (stream->max_time > 0 &&
  580. packet->dts_usec - stream->cur_time >= stream->max_time)
  581. return true;
  582. return false;
  583. }
  584. static bool send_new_filename(struct ffmpeg_muxer *stream, const char *filename)
  585. {
  586. size_t ret;
  587. uint32_t size = (uint32_t)strlen(filename);
  588. struct ffm_packet_info info = {.type = FFM_PACKET_CHANGE_FILE,
  589. .size = size};
  590. ret = os_process_pipe_write(stream->pipe, (const uint8_t *)&info,
  591. sizeof(info));
  592. if (ret != sizeof(info)) {
  593. warn("os_process_pipe_write for info structure failed");
  594. signal_failure(stream);
  595. return false;
  596. }
  597. ret = os_process_pipe_write(stream->pipe, (const uint8_t *)filename,
  598. size);
  599. if (ret != size) {
  600. warn("os_process_pipe_write for packet data failed");
  601. signal_failure(stream);
  602. return false;
  603. }
  604. return true;
  605. }
  606. static bool prepare_split_file(struct ffmpeg_muxer *stream,
  607. struct encoder_packet *packet)
  608. {
  609. generate_filename(stream, &stream->path, stream->allow_overwrite);
  610. info("Changing output file to '%s'", stream->path.array);
  611. if (!send_new_filename(stream, stream->path.array)) {
  612. warn("Failed to send new file name");
  613. return false;
  614. }
  615. calldata_t cd = {0};
  616. signal_handler_t *sh = obs_output_get_signal_handler(stream->output);
  617. calldata_set_string(&cd, "next_file", stream->path.array);
  618. signal_handler_signal(sh, "file_changed", &cd);
  619. calldata_free(&cd);
  620. if (!send_headers(stream))
  621. return false;
  622. stream->cur_size = 0;
  623. stream->cur_time = packet->dts_usec;
  624. ts_offset_clear(stream);
  625. return true;
  626. }
  627. static inline bool has_audio(struct ffmpeg_muxer *stream)
  628. {
  629. return !!obs_output_get_audio_encoder(stream->output, 0);
  630. }
  631. static void push_back_packet(struct darray *packets,
  632. struct encoder_packet *packet)
  633. {
  634. struct encoder_packet pkt;
  635. obs_encoder_packet_ref(&pkt, packet);
  636. darray_push_back(sizeof(pkt), packets, &pkt);
  637. }
  638. static void ffmpeg_mux_data(void *data, struct encoder_packet *packet)
  639. {
  640. struct ffmpeg_muxer *stream = data;
  641. if (!active(stream))
  642. return;
  643. /* encoder failure */
  644. if (!packet) {
  645. deactivate(stream, OBS_OUTPUT_ENCODE_ERROR);
  646. return;
  647. }
  648. if (stream->split_file && stream->mux_packets.num) {
  649. int64_t pts_usec = packet_pts_usec(packet);
  650. struct encoder_packet *first_pkt = stream->mux_packets.array;
  651. int64_t first_pts_usec = packet_pts_usec(first_pkt);
  652. if (pts_usec >= first_pts_usec) {
  653. if (packet->type != OBS_ENCODER_AUDIO) {
  654. push_back_packet(&stream->mux_packets.da,
  655. packet);
  656. return;
  657. }
  658. if (!prepare_split_file(stream, first_pkt))
  659. return;
  660. stream->split_file_ready = true;
  661. }
  662. } else if (stream->split_file && should_split(stream, packet)) {
  663. if (has_audio(stream)) {
  664. push_back_packet(&stream->mux_packets.da, packet);
  665. return;
  666. } else {
  667. if (!prepare_split_file(stream, packet))
  668. return;
  669. stream->split_file_ready = true;
  670. }
  671. }
  672. if (!stream->sent_headers) {
  673. if (!send_headers(stream))
  674. return;
  675. stream->sent_headers = true;
  676. if (stream->split_file)
  677. stream->cur_time = packet->dts_usec;
  678. }
  679. if (stopping(stream)) {
  680. if (packet->sys_dts_usec >= stream->stop_ts) {
  681. deactivate(stream, 0);
  682. return;
  683. }
  684. }
  685. if (stream->split_file && stream->split_file_ready) {
  686. for (size_t i = 0; i < stream->mux_packets.num; i++) {
  687. struct encoder_packet *pkt =
  688. &stream->mux_packets.array[i];
  689. ts_offset_update(stream, pkt);
  690. write_packet(stream, pkt);
  691. obs_encoder_packet_release(pkt);
  692. }
  693. da_free(stream->mux_packets);
  694. stream->split_file_ready = false;
  695. os_atomic_set_bool(&stream->manual_split, false);
  696. }
  697. if (stream->split_file)
  698. ts_offset_update(stream, packet);
  699. write_packet(stream, packet);
  700. }
  701. static obs_properties_t *ffmpeg_mux_properties(void *unused)
  702. {
  703. UNUSED_PARAMETER(unused);
  704. obs_properties_t *props = obs_properties_create();
  705. obs_properties_add_text(props, "path", obs_module_text("FilePath"),
  706. OBS_TEXT_DEFAULT);
  707. return props;
  708. }
  709. uint64_t ffmpeg_mux_total_bytes(void *data)
  710. {
  711. struct ffmpeg_muxer *stream = data;
  712. return stream->total_bytes;
  713. }
  714. struct obs_output_info ffmpeg_muxer = {
  715. .id = "ffmpeg_muxer",
  716. .flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED | OBS_OUTPUT_MULTI_TRACK |
  717. OBS_OUTPUT_CAN_PAUSE,
  718. .get_name = ffmpeg_mux_getname,
  719. .create = ffmpeg_mux_create,
  720. .destroy = ffmpeg_mux_destroy,
  721. .start = ffmpeg_mux_start,
  722. .stop = ffmpeg_mux_stop,
  723. .encoded_packet = ffmpeg_mux_data,
  724. .get_total_bytes = ffmpeg_mux_total_bytes,
  725. .get_properties = ffmpeg_mux_properties,
  726. };
  727. static int connect_time(struct ffmpeg_muxer *stream)
  728. {
  729. UNUSED_PARAMETER(stream);
  730. /* TODO */
  731. return 0;
  732. }
  733. #ifndef NEW_MPEGTS_OUTPUT
  734. static int ffmpeg_mpegts_mux_connect_time(void *data)
  735. {
  736. struct ffmpeg_muxer *stream = data;
  737. /* TODO */
  738. return connect_time(stream);
  739. }
  740. struct obs_output_info ffmpeg_mpegts_muxer = {
  741. .id = "ffmpeg_mpegts_muxer",
  742. .flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED | OBS_OUTPUT_MULTI_TRACK |
  743. OBS_OUTPUT_SERVICE,
  744. .encoded_video_codecs = "h264;av1",
  745. .encoded_audio_codecs = "aac",
  746. .get_name = ffmpeg_mpegts_mux_getname,
  747. .create = ffmpeg_mux_create,
  748. .destroy = ffmpeg_mux_destroy,
  749. .start = ffmpeg_mux_start,
  750. .stop = ffmpeg_mux_stop,
  751. .encoded_packet = ffmpeg_mux_data,
  752. .get_total_bytes = ffmpeg_mux_total_bytes,
  753. .get_properties = ffmpeg_mux_properties,
  754. .get_connect_time_ms = ffmpeg_mpegts_mux_connect_time,
  755. };
  756. #endif
  757. /* ------------------------------------------------------------------------ */
  758. static const char *replay_buffer_getname(void *type)
  759. {
  760. UNUSED_PARAMETER(type);
  761. return obs_module_text("ReplayBuffer");
  762. }
  763. static void replay_buffer_hotkey(void *data, obs_hotkey_id id,
  764. obs_hotkey_t *hotkey, bool pressed)
  765. {
  766. UNUSED_PARAMETER(id);
  767. UNUSED_PARAMETER(hotkey);
  768. if (!pressed)
  769. return;
  770. struct ffmpeg_muxer *stream = data;
  771. if (os_atomic_load_bool(&stream->active)) {
  772. obs_encoder_t *vencoder =
  773. obs_output_get_video_encoder(stream->output);
  774. if (obs_encoder_paused(vencoder)) {
  775. info("Could not save buffer because encoders paused");
  776. return;
  777. }
  778. stream->save_ts = os_gettime_ns() / 1000LL;
  779. }
  780. }
  781. static void save_replay_proc(void *data, calldata_t *cd)
  782. {
  783. replay_buffer_hotkey(data, 0, NULL, true);
  784. UNUSED_PARAMETER(cd);
  785. }
  786. static void get_last_replay(void *data, calldata_t *cd)
  787. {
  788. struct ffmpeg_muxer *stream = data;
  789. if (!os_atomic_load_bool(&stream->muxing))
  790. calldata_set_string(cd, "path", stream->path.array);
  791. }
  792. static void *replay_buffer_create(obs_data_t *settings, obs_output_t *output)
  793. {
  794. UNUSED_PARAMETER(settings);
  795. struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream));
  796. stream->output = output;
  797. stream->hotkey =
  798. obs_hotkey_register_output(output, "ReplayBuffer.Save",
  799. obs_module_text("ReplayBuffer.Save"),
  800. replay_buffer_hotkey, stream);
  801. proc_handler_t *ph = obs_output_get_proc_handler(output);
  802. proc_handler_add(ph, "void save()", save_replay_proc, stream);
  803. proc_handler_add(ph, "void get_last_replay(out string path)",
  804. get_last_replay, stream);
  805. signal_handler_t *sh = obs_output_get_signal_handler(output);
  806. signal_handler_add(sh, "void saved()");
  807. return stream;
  808. }
  809. static void replay_buffer_destroy(void *data)
  810. {
  811. struct ffmpeg_muxer *stream = data;
  812. if (stream->hotkey)
  813. obs_hotkey_unregister(stream->hotkey);
  814. ffmpeg_mux_destroy(data);
  815. }
  816. static bool replay_buffer_start(void *data)
  817. {
  818. struct ffmpeg_muxer *stream = data;
  819. if (!obs_output_can_begin_data_capture(stream->output, 0))
  820. return false;
  821. if (!obs_output_initialize_encoders(stream->output, 0))
  822. return false;
  823. obs_data_t *s = obs_output_get_settings(stream->output);
  824. stream->max_time = obs_data_get_int(s, "max_time_sec") * 1000000LL;
  825. stream->max_size = obs_data_get_int(s, "max_size_mb") * (1024 * 1024);
  826. obs_data_release(s);
  827. os_atomic_set_bool(&stream->active, true);
  828. os_atomic_set_bool(&stream->capturing, true);
  829. stream->total_bytes = 0;
  830. obs_output_begin_data_capture(stream->output, 0);
  831. return true;
  832. }
  833. static bool purge_front(struct ffmpeg_muxer *stream)
  834. {
  835. struct encoder_packet pkt;
  836. bool keyframe;
  837. if (!stream->packets.size)
  838. return false;
  839. circlebuf_pop_front(&stream->packets, &pkt, sizeof(pkt));
  840. keyframe = pkt.type == OBS_ENCODER_VIDEO && pkt.keyframe;
  841. if (keyframe)
  842. stream->keyframes--;
  843. if (!stream->packets.size) {
  844. stream->cur_size = 0;
  845. stream->cur_time = 0;
  846. } else {
  847. struct encoder_packet first;
  848. circlebuf_peek_front(&stream->packets, &first, sizeof(first));
  849. stream->cur_time = first.dts_usec;
  850. stream->cur_size -= (int64_t)pkt.size;
  851. }
  852. obs_encoder_packet_release(&pkt);
  853. return keyframe;
  854. }
  855. static inline void purge(struct ffmpeg_muxer *stream)
  856. {
  857. if (purge_front(stream)) {
  858. struct encoder_packet pkt;
  859. for (;;) {
  860. if (!stream->packets.size)
  861. return;
  862. circlebuf_peek_front(&stream->packets, &pkt,
  863. sizeof(pkt));
  864. if (pkt.type == OBS_ENCODER_VIDEO && pkt.keyframe)
  865. return;
  866. purge_front(stream);
  867. }
  868. }
  869. }
  870. static inline void replay_buffer_purge(struct ffmpeg_muxer *stream,
  871. struct encoder_packet *pkt)
  872. {
  873. if (stream->max_size) {
  874. if (!stream->packets.size || stream->keyframes <= 2)
  875. return;
  876. while ((stream->cur_size + (int64_t)pkt->size) >
  877. stream->max_size)
  878. purge(stream);
  879. }
  880. if (!stream->packets.size || stream->keyframes <= 2)
  881. return;
  882. while ((pkt->dts_usec - stream->cur_time) > stream->max_time)
  883. purge(stream);
  884. }
  885. static void insert_packet(struct darray *array, struct encoder_packet *packet,
  886. int64_t video_offset, int64_t *audio_offsets,
  887. int64_t video_pts_offset, int64_t *audio_dts_offsets)
  888. {
  889. struct encoder_packet pkt;
  890. DARRAY(struct encoder_packet) packets;
  891. packets.da = *array;
  892. size_t idx;
  893. obs_encoder_packet_ref(&pkt, packet);
  894. if (pkt.type == OBS_ENCODER_VIDEO) {
  895. pkt.dts_usec -= video_offset;
  896. pkt.dts -= video_pts_offset;
  897. pkt.pts -= video_pts_offset;
  898. } else {
  899. pkt.dts_usec -= audio_offsets[pkt.track_idx];
  900. pkt.dts -= audio_dts_offsets[pkt.track_idx];
  901. pkt.pts -= audio_dts_offsets[pkt.track_idx];
  902. }
  903. for (idx = packets.num; idx > 0; idx--) {
  904. struct encoder_packet *p = packets.array + (idx - 1);
  905. if (p->dts_usec < pkt.dts_usec)
  906. break;
  907. }
  908. da_insert(packets, idx, &pkt);
  909. *array = packets.da;
  910. }
  911. static void *replay_buffer_mux_thread(void *data)
  912. {
  913. struct ffmpeg_muxer *stream = data;
  914. bool error = false;
  915. start_pipe(stream, stream->path.array);
  916. if (!stream->pipe) {
  917. warn("Failed to create process pipe");
  918. error = true;
  919. goto error;
  920. }
  921. if (!send_headers(stream)) {
  922. warn("Could not write headers for file '%s'",
  923. stream->path.array);
  924. error = true;
  925. goto error;
  926. }
  927. for (size_t i = 0; i < stream->mux_packets.num; i++) {
  928. struct encoder_packet *pkt = &stream->mux_packets.array[i];
  929. write_packet(stream, pkt);
  930. obs_encoder_packet_release(pkt);
  931. }
  932. info("Wrote replay buffer to '%s'", stream->path.array);
  933. error:
  934. os_process_pipe_destroy(stream->pipe);
  935. stream->pipe = NULL;
  936. if (error) {
  937. for (size_t i = 0; i < stream->mux_packets.num; i++)
  938. obs_encoder_packet_release(
  939. &stream->mux_packets.array[i]);
  940. }
  941. da_free(stream->mux_packets);
  942. os_atomic_set_bool(&stream->muxing, false);
  943. if (!error) {
  944. calldata_t cd = {0};
  945. signal_handler_t *sh =
  946. obs_output_get_signal_handler(stream->output);
  947. signal_handler_signal(sh, "saved", &cd);
  948. }
  949. return NULL;
  950. }
  951. static void replay_buffer_save(struct ffmpeg_muxer *stream)
  952. {
  953. const size_t size = sizeof(struct encoder_packet);
  954. size_t num_packets = stream->packets.size / size;
  955. da_reserve(stream->mux_packets, num_packets);
  956. /* ---------------------------- */
  957. /* reorder packets */
  958. bool found_video = false;
  959. bool found_audio[MAX_AUDIO_MIXES] = {0};
  960. int64_t video_offset = 0;
  961. int64_t video_pts_offset = 0;
  962. int64_t audio_offsets[MAX_AUDIO_MIXES] = {0};
  963. int64_t audio_dts_offsets[MAX_AUDIO_MIXES] = {0};
  964. for (size_t i = 0; i < num_packets; i++) {
  965. struct encoder_packet *pkt;
  966. pkt = circlebuf_data(&stream->packets, i * size);
  967. if (pkt->type == OBS_ENCODER_VIDEO) {
  968. if (!found_video) {
  969. video_pts_offset = pkt->pts;
  970. video_offset = video_pts_offset * 1000000 /
  971. pkt->timebase_den;
  972. found_video = true;
  973. }
  974. } else {
  975. if (!found_audio[pkt->track_idx]) {
  976. found_audio[pkt->track_idx] = true;
  977. audio_offsets[pkt->track_idx] = pkt->dts_usec;
  978. audio_dts_offsets[pkt->track_idx] = pkt->dts;
  979. }
  980. }
  981. insert_packet(&stream->mux_packets.da, pkt, video_offset,
  982. audio_offsets, video_pts_offset,
  983. audio_dts_offsets);
  984. }
  985. generate_filename(stream, &stream->path, true);
  986. os_atomic_set_bool(&stream->muxing, true);
  987. stream->mux_thread_joinable = pthread_create(&stream->mux_thread, NULL,
  988. replay_buffer_mux_thread,
  989. stream) == 0;
  990. if (!stream->mux_thread_joinable) {
  991. warn("Failed to create muxer thread");
  992. os_atomic_set_bool(&stream->muxing, false);
  993. }
  994. }
  995. static void deactivate_replay_buffer(struct ffmpeg_muxer *stream, int code)
  996. {
  997. if (code) {
  998. obs_output_signal_stop(stream->output, code);
  999. } else if (stopping(stream)) {
  1000. obs_output_end_data_capture(stream->output);
  1001. }
  1002. os_atomic_set_bool(&stream->active, false);
  1003. os_atomic_set_bool(&stream->sent_headers, false);
  1004. os_atomic_set_bool(&stream->stopping, false);
  1005. replay_buffer_clear(stream);
  1006. }
  1007. static void replay_buffer_data(void *data, struct encoder_packet *packet)
  1008. {
  1009. struct ffmpeg_muxer *stream = data;
  1010. struct encoder_packet pkt;
  1011. if (!active(stream))
  1012. return;
  1013. /* encoder failure */
  1014. if (!packet) {
  1015. deactivate_replay_buffer(stream, OBS_OUTPUT_ENCODE_ERROR);
  1016. return;
  1017. }
  1018. if (stopping(stream)) {
  1019. if (packet->sys_dts_usec >= stream->stop_ts) {
  1020. deactivate_replay_buffer(stream, 0);
  1021. return;
  1022. }
  1023. }
  1024. obs_encoder_packet_ref(&pkt, packet);
  1025. replay_buffer_purge(stream, &pkt);
  1026. if (!stream->packets.size)
  1027. stream->cur_time = pkt.dts_usec;
  1028. stream->cur_size += pkt.size;
  1029. circlebuf_push_back(&stream->packets, packet, sizeof(*packet));
  1030. if (packet->type == OBS_ENCODER_VIDEO && packet->keyframe)
  1031. stream->keyframes++;
  1032. if (stream->save_ts && packet->sys_dts_usec >= stream->save_ts) {
  1033. if (os_atomic_load_bool(&stream->muxing))
  1034. return;
  1035. if (stream->mux_thread_joinable) {
  1036. pthread_join(stream->mux_thread, NULL);
  1037. stream->mux_thread_joinable = false;
  1038. }
  1039. stream->save_ts = 0;
  1040. replay_buffer_save(stream);
  1041. }
  1042. }
  1043. static void replay_buffer_defaults(obs_data_t *s)
  1044. {
  1045. obs_data_set_default_int(s, "max_time_sec", 15);
  1046. obs_data_set_default_int(s, "max_size_mb", 500);
  1047. obs_data_set_default_string(s, "format", "%CCYY-%MM-%DD %hh-%mm-%ss");
  1048. obs_data_set_default_string(s, "extension", "mp4");
  1049. obs_data_set_default_bool(s, "allow_spaces", true);
  1050. }
  1051. struct obs_output_info replay_buffer = {
  1052. .id = "replay_buffer",
  1053. .flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED | OBS_OUTPUT_MULTI_TRACK |
  1054. OBS_OUTPUT_CAN_PAUSE,
  1055. .get_name = replay_buffer_getname,
  1056. .create = replay_buffer_create,
  1057. .destroy = replay_buffer_destroy,
  1058. .start = replay_buffer_start,
  1059. .stop = ffmpeg_mux_stop,
  1060. .encoded_packet = replay_buffer_data,
  1061. .get_total_bytes = ffmpeg_mux_total_bytes,
  1062. .get_defaults = replay_buffer_defaults,
  1063. };