obs-encoder.c 23.4 KB
Newer Older
1
/******************************************************************************
2
    Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include "obs.h"
J
jp9000 已提交
19
#include "obs-internal.h"
20

21
struct obs_encoder_info *find_encoder(const char *id)
22 23
{
	for (size_t i = 0; i < obs->encoder_types.num; i++) {
J
jp9000 已提交
24
		struct obs_encoder_info *info = obs->encoder_types.array+i;
25 26 27 28 29 30 31 32

		if (strcmp(info->id, id) == 0)
			return info;
	}

	return NULL;
}

33
const char *obs_encoder_get_display_name(const char *id)
34
{
J
jp9000 已提交
35
	struct obs_encoder_info *ei = find_encoder(id);
36
	return ei ? ei->get_name() : NULL;
37 38
}

39
static bool init_encoder(struct obs_encoder *encoder, const char *name,
40
		obs_data_t *settings, obs_data_t *hotkey_data)
41
{
42 43
	pthread_mutexattr_t attr;

J
jp9000 已提交
44 45 46
	pthread_mutex_init_value(&encoder->callbacks_mutex);
	pthread_mutex_init_value(&encoder->outputs_mutex);

47 48 49 50
	if (pthread_mutexattr_init(&attr) != 0)
		return false;
	if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
		return false;
51 52
	if (!obs_context_data_init(&encoder->context, settings, name,
				hotkey_data))
53
		return false;
54
	if (pthread_mutex_init(&encoder->callbacks_mutex, &attr) != 0)
55
		return false;
J
jp9000 已提交
56 57
	if (pthread_mutex_init(&encoder->outputs_mutex, NULL) != 0)
		return false;
58

59 60
	if (encoder->info.get_defaults)
		encoder->info.get_defaults(encoder->context.settings);
61 62 63 64 65 66

	return true;
}

static struct obs_encoder *create_encoder(const char *id,
		enum obs_encoder_type type, const char *name,
67
		obs_data_t *settings, size_t mixer_idx, obs_data_t *hotkey_data)
68 69
{
	struct obs_encoder *encoder;
J
jp9000 已提交
70
	struct obs_encoder_info *ei = find_encoder(id);
71
	bool success;
72

73
	if (!ei || ei->type != type)
74 75
		return NULL;

76
	encoder = bzalloc(sizeof(struct obs_encoder));
77
	encoder->info = *ei;
78
	encoder->mixer_idx = mixer_idx;
79

80
	success = init_encoder(encoder, name, settings, hotkey_data);
81
	if (!success) {
82
		blog(LOG_ERROR, "creating encoder '%s' (%s) failed", name, id);
83
		obs_encoder_destroy(encoder);
84
		return NULL;
85 86
	}

87 88 89
	encoder->control = bzalloc(sizeof(obs_weak_encoder_t));
	encoder->control->encoder = encoder;

90 91 92 93
	obs_context_data_insert(&encoder->context,
			&obs->data.encoders_mutex,
			&obs->data.first_encoder);

94
	blog(LOG_INFO, "encoder '%s' (%s) created", name, id);
95 96
	return encoder;
}
J
jp9000 已提交
97

98
obs_encoder_t *obs_video_encoder_create(const char *id, const char *name,
99
		obs_data_t *settings, obs_data_t *hotkey_data)
100
{
101
	if (!name || !id) return NULL;
102 103
	return create_encoder(id, OBS_ENCODER_VIDEO, name, settings, 0,
			hotkey_data);
104 105
}

106
obs_encoder_t *obs_audio_encoder_create(const char *id, const char *name,
107
		obs_data_t *settings, size_t mixer_idx, obs_data_t *hotkey_data)
108
{
109
	if (!name || !id) return NULL;
110 111
	return create_encoder(id, OBS_ENCODER_AUDIO, name, settings, mixer_idx,
			hotkey_data);
112 113 114
}

static void receive_video(void *param, struct video_data *frame);
115
static void receive_audio(void *param, size_t mix_idx, struct audio_data *data);
116

117
static inline void get_audio_info(const struct obs_encoder *encoder,
118
		struct audio_convert_info *info)
119
{
120
	const struct audio_output_info *aoi;
121
	aoi = audio_output_get_info(encoder->media);
122

123 124 125 126 127 128 129
	if (info->format == AUDIO_FORMAT_UNKNOWN)
		info->format = aoi->format;
	if (!info->samples_per_sec)
		info->samples_per_sec = aoi->samples_per_sec;
	if (info->speakers == SPEAKERS_UNKNOWN)
		info->speakers = aoi->speakers;

130 131
	if (encoder->info.get_audio_info)
		encoder->info.get_audio_info(encoder->context.data, info);
132 133
}

134
static inline void get_video_info(struct obs_encoder *encoder,
135
		struct video_scale_info *info)
136
{
137 138 139 140 141 142 143 144 145
	const struct video_output_info *voi;
	voi = video_output_get_info(encoder->media);

	info->format     = voi->format;
	info->colorspace = voi->colorspace;
	info->range      = voi->range;
	info->width      = obs_encoder_get_width(encoder);
	info->height     = obs_encoder_get_height(encoder);

146
	if (encoder->info.get_video_info)
147
		encoder->info.get_video_info(encoder->context.data, info);
148

149 150
	if (info->width != voi->width || info->height != voi->height)
		obs_encoder_set_scaled_size(encoder, info->width, info->height);
151 152
}

153
static inline bool has_scaling(const struct obs_encoder *encoder)
154 155 156 157 158 159 160 161 162
{
	uint32_t video_width  = video_output_get_width(encoder->media);
	uint32_t video_height = video_output_get_height(encoder->media);

	return encoder->scaled_width && encoder->scaled_height &&
		(video_width  != encoder->scaled_width ||
		 video_height != encoder->scaled_height);
}

163 164 165
static void add_connection(struct obs_encoder *encoder)
{
	if (encoder->info.type == OBS_ENCODER_AUDIO) {
166
		struct audio_convert_info audio_info = {0};
167
		get_audio_info(encoder, &audio_info);
168

169 170
		audio_output_connect(encoder->media, encoder->mixer_idx,
				&audio_info, receive_audio, encoder);
171
	} else {
172 173
		struct video_scale_info info = {0};
		get_video_info(encoder, &info);
174

175
		video_output_connect(encoder->media, &info, receive_video,
176
			encoder);
177
	}
J
jp9000 已提交
178 179

	encoder->active = true;
180
}
181

182 183 184
static void remove_connection(struct obs_encoder *encoder)
{
	if (encoder->info.type == OBS_ENCODER_AUDIO)
185 186
		audio_output_disconnect(encoder->media, encoder->mixer_idx,
				receive_audio, encoder);
187
	else
J
jp9000 已提交
188
		video_output_disconnect(encoder->media, receive_video,
189
				encoder);
J
jp9000 已提交
190 191

	encoder->active = false;
192
}
J
jp9000 已提交
193

194 195 196 197 198 199 200 201 202
static inline void free_audio_buffers(struct obs_encoder *encoder)
{
	for (size_t i = 0; i < MAX_AV_PLANES; i++) {
		circlebuf_free(&encoder->audio_input_buffer[i]);
		bfree(encoder->audio_output_buffer[i]);
		encoder->audio_output_buffer[i] = NULL;
	}
}

203
static void obs_encoder_actually_destroy(obs_encoder_t *encoder)
204 205
{
	if (encoder) {
J
jp9000 已提交
206 207 208 209 210 211 212 213
		pthread_mutex_lock(&encoder->outputs_mutex);
		for (size_t i = 0; i < encoder->outputs.num; i++) {
			struct obs_output *output = encoder->outputs.array[i];
			obs_output_remove_encoder(output, encoder);
		}
		da_free(encoder->outputs);
		pthread_mutex_unlock(&encoder->outputs_mutex);

214 215
		blog(LOG_INFO, "encoder '%s' destroyed", encoder->context.name);

216 217
		free_audio_buffers(encoder);

218 219
		if (encoder->context.data)
			encoder->info.destroy(encoder->context.data);
220
		da_free(encoder->callbacks);
J
jp9000 已提交
221 222
		pthread_mutex_destroy(&encoder->callbacks_mutex);
		pthread_mutex_destroy(&encoder->outputs_mutex);
223
		obs_context_data_free(&encoder->context);
J
jp9000 已提交
224
		bfree(encoder);
225
	}
226 227
}

J
jp9000 已提交
228 229
/* does not actually destroy the encoder until all connections to it have been
 * removed. (full reference counting really would have been superfluous) */
230
void obs_encoder_destroy(obs_encoder_t *encoder)
231 232
{
	if (encoder) {
J
jp9000 已提交
233
		bool destroy;
234

235
		obs_context_data_remove(&encoder->context);
236

J
jp9000 已提交
237 238 239 240 241 242 243 244
		pthread_mutex_lock(&encoder->callbacks_mutex);
		destroy = encoder->callbacks.num == 0;
		if (!destroy)
			encoder->destroy_on_stop = true;
		pthread_mutex_unlock(&encoder->callbacks_mutex);

		if (destroy)
			obs_encoder_actually_destroy(encoder);
245 246 247
	}
}

248
const char *obs_encoder_get_name(const obs_encoder_t *encoder)
J
jp9000 已提交
249 250 251 252
{
	return encoder ? encoder->context.name : NULL;
}

253 254 255 256 257 258 259 260
void obs_encoder_set_name(obs_encoder_t *encoder, const char *name)
{
	if (!encoder) return;

	if (name && *name && strcmp(name, encoder->context.name) != 0)
		obs_context_data_setname(&encoder->context, name);
}

261
static inline obs_data_t *get_defaults(const struct obs_encoder_info *info)
J
jp9000 已提交
262
{
263
	obs_data_t *settings = obs_data_create();
264 265
	if (info->get_defaults)
		info->get_defaults(settings);
J
jp9000 已提交
266 267 268
	return settings;
}

269
obs_data_t *obs_encoder_defaults(const char *id)
J
jp9000 已提交
270
{
J
jp9000 已提交
271
	const struct obs_encoder_info *info = find_encoder(id);
J
jp9000 已提交
272
	return (info) ? get_defaults(info) : NULL;
J
jp9000 已提交
273 274
}

275
obs_properties_t *obs_get_encoder_properties(const char *id)
J
jp9000 已提交
276
{
J
jp9000 已提交
277
	const struct obs_encoder_info *ei = find_encoder(id);
278
	if (ei && ei->get_properties) {
279 280
		obs_data_t       *defaults = get_defaults(ei);
		obs_properties_t *properties;
J
jp9000 已提交
281

282
		properties = ei->get_properties(NULL);
J
jp9000 已提交
283 284 285 286
		obs_properties_apply_settings(properties, defaults);
		obs_data_release(defaults);
		return properties;
	}
J
jp9000 已提交
287 288 289
	return NULL;
}

290
obs_properties_t *obs_encoder_properties(const obs_encoder_t *encoder)
291
{
292
	if (encoder && encoder->info.get_properties) {
293
		obs_properties_t *props;
294
		props = encoder->info.get_properties(encoder->context.data);
295
		obs_properties_apply_settings(props, encoder->context.settings);
J
jp9000 已提交
296 297
		return props;
	}
298 299 300
	return NULL;
}

301
void obs_encoder_update(obs_encoder_t *encoder, obs_data_t *settings)
302
{
J
jp9000 已提交
303 304
	if (!encoder) return;

305 306 307 308 309
	obs_data_apply(encoder->context.settings, settings);

	if (encoder->info.update && encoder->context.data)
		encoder->info.update(encoder->context.data,
				encoder->context.settings);
310 311
}

312 313
bool obs_encoder_get_extra_data(const obs_encoder_t *encoder,
		uint8_t **extra_data, size_t *size)
314
{
315 316
	if (encoder && encoder->info.get_extra_data && encoder->context.data)
		return encoder->info.get_extra_data(encoder->context.data,
317
				extra_data, size);
J
jp9000 已提交
318 319

	return false;
320 321
}

322
obs_data_t *obs_encoder_get_settings(const obs_encoder_t *encoder)
323
{
J
jp9000 已提交
324 325
	if (!encoder) return NULL;

326 327
	obs_data_addref(encoder->context.settings);
	return encoder->context.settings;
328 329
}

330 331 332 333 334 335 336 337 338 339 340
static inline void reset_audio_buffers(struct obs_encoder *encoder)
{
	free_audio_buffers(encoder);

	for (size_t i = 0; i < encoder->planes; i++)
		encoder->audio_output_buffer[i] =
			bmalloc(encoder->framesize_bytes);
}

static void intitialize_audio_encoder(struct obs_encoder *encoder)
{
341
	struct audio_convert_info info = {0};
342 343 344 345 346
	get_audio_info(encoder, &info);

	encoder->samplerate = info.samples_per_sec;
	encoder->planes     = get_audio_planes(info.format, info.speakers);
	encoder->blocksize  = get_audio_size(info.format, info.speakers, 1);
347 348
	encoder->framesize  = encoder->info.get_frame_size(
			encoder->context.data);
349 350 351 352 353

	encoder->framesize_bytes = encoder->blocksize * encoder->framesize;
	reset_audio_buffers(encoder);
}

354
bool obs_encoder_initialize(obs_encoder_t *encoder)
J
jp9000 已提交
355 356 357 358 359 360
{
	if (!encoder) return false;

	if (encoder->active)
		return true;

361 362
	if (encoder->context.data)
		encoder->info.destroy(encoder->context.data);
363

364 365 366
	encoder->context.data = encoder->info.create(encoder->context.settings,
			encoder);
	if (!encoder->context.data)
367 368 369 370 371 372 373 374 375
		return false;

	encoder->paired_encoder  = NULL;
	encoder->start_ts        = 0;

	if (encoder->info.type == OBS_ENCODER_AUDIO)
		intitialize_audio_encoder(encoder);

	return true;
J
jp9000 已提交
376 377
}

378
static inline size_t get_callback_idx(
379
		const struct obs_encoder *encoder,
380 381 382 383 384 385 386 387 388 389 390 391 392
		void (*new_packet)(void *param, struct encoder_packet *packet),
		void *param)
{
	for (size_t i = 0; i < encoder->callbacks.num; i++) {
		struct encoder_callback *cb = encoder->callbacks.array+i;

		if (cb->new_packet == new_packet && cb->param == param)
			return i;
	}

	return DARRAY_INVALID;
}

393
void obs_encoder_start(obs_encoder_t *encoder,
J
jp9000 已提交
394 395
		void (*new_packet)(void *param, struct encoder_packet *packet),
		void *param)
396
{
397 398 399
	struct encoder_callback cb = {false, new_packet, param};
	bool first   = false;

400
	if (!encoder || !new_packet || !encoder->context.data) return;
401 402 403 404 405

	pthread_mutex_lock(&encoder->callbacks_mutex);

	first = (encoder->callbacks.num == 0);

406 407 408
	size_t idx = get_callback_idx(encoder, new_packet, param);
	if (idx == DARRAY_INVALID)
		da_push_back(encoder->callbacks, &cb);
409 410 411 412 413 414 415

	pthread_mutex_unlock(&encoder->callbacks_mutex);

	if (first) {
		encoder->cur_pts = 0;
		add_connection(encoder);
	}
416 417
}

418
void obs_encoder_stop(obs_encoder_t *encoder,
J
jp9000 已提交
419 420
		void (*new_packet)(void *param, struct encoder_packet *packet),
		void *param)
421
{
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
	bool   last = false;
	size_t idx;

	if (!encoder) return;

	pthread_mutex_lock(&encoder->callbacks_mutex);

	idx = get_callback_idx(encoder, new_packet, param);
	if (idx != DARRAY_INVALID) {
		da_erase(encoder->callbacks, idx);
		last = (encoder->callbacks.num == 0);
	}

	pthread_mutex_unlock(&encoder->callbacks_mutex);

J
jp9000 已提交
437
	if (last) {
438
		remove_connection(encoder);
J
jp9000 已提交
439 440 441 442

		if (encoder->destroy_on_stop)
			obs_encoder_actually_destroy(encoder);
	}
443 444
}

445
const char *obs_encoder_get_codec(const obs_encoder_t *encoder)
446 447 448 449
{
	return encoder ? encoder->info.codec : NULL;
}

450 451 452 453 454 455
const char *obs_get_encoder_codec(const char *id)
{
	struct obs_encoder_info *info = find_encoder(id);
	return info ? info->codec : NULL;
}

456 457 458 459 460 461 462 463 464 465 466
enum obs_encoder_type obs_encoder_get_type(const obs_encoder_t *encoder)
{
	return encoder ? encoder->info.type : OBS_ENCODER_AUDIO;
}

enum obs_encoder_type obs_get_encoder_type(const char *id)
{
	struct obs_encoder_info *info = find_encoder(id);
	return info ? info->type : OBS_ENCODER_AUDIO;
}

467
void obs_encoder_set_scaled_size(obs_encoder_t *encoder, uint32_t width,
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
		uint32_t height)
{
	if (!encoder || encoder->info.type != OBS_ENCODER_VIDEO)
		return;

	if (encoder->active) {
		blog(LOG_WARNING, "encoder '%s': Cannot set the scaled "
		                  "resolution while the encoder is active",
		                  obs_encoder_get_name(encoder));
		return;
	}

	encoder->scaled_width  = width;
	encoder->scaled_height = height;
}

484
uint32_t obs_encoder_get_width(const obs_encoder_t *encoder)
485 486 487 488 489 490 491 492 493 494
{
	if (!encoder || !encoder->media ||
	    encoder->info.type != OBS_ENCODER_VIDEO)
		return 0;

	return encoder->scaled_width != 0 ?
		encoder->scaled_width :
		video_output_get_width(encoder->media);
}

495
uint32_t obs_encoder_get_height(const obs_encoder_t *encoder)
496 497 498 499 500 501 502 503 504 505
{
	if (!encoder || !encoder->media ||
	    encoder->info.type != OBS_ENCODER_VIDEO)
		return 0;

	return encoder->scaled_width != 0 ?
		encoder->scaled_height :
		video_output_get_height(encoder->media);
}

506 507 508 509 510 511 512 513 514 515 516
uint32_t obs_encoder_get_sample_rate(const obs_encoder_t *encoder)
{
	if (!encoder || !encoder->media ||
	    encoder->info.type != OBS_ENCODER_AUDIO)
		return 0;

	return encoder->samplerate != 0 ?
		encoder->samplerate :
		audio_output_get_sample_rate(encoder->media);
}

517
void obs_encoder_set_video(obs_encoder_t *encoder, video_t *video)
518 519 520 521 522 523
{
	const struct video_output_info *voi;

	if (!video || !encoder || encoder->info.type != OBS_ENCODER_VIDEO)
		return;

524
	voi = video_output_get_info(video);
525 526 527 528 529 530

	encoder->media        = video;
	encoder->timebase_num = voi->fps_den;
	encoder->timebase_den = voi->fps_num;
}

531
void obs_encoder_set_audio(obs_encoder_t *encoder, audio_t *audio)
532 533 534 535 536 537
{
	if (!audio || !encoder || encoder->info.type != OBS_ENCODER_AUDIO)
		return;

	encoder->media        = audio;
	encoder->timebase_num = 1;
538
	encoder->timebase_den = audio_output_get_sample_rate(audio);
539 540
}

541
video_t *obs_encoder_video(const obs_encoder_t *encoder)
542 543
{
	return (encoder && encoder->info.type == OBS_ENCODER_VIDEO) ?
J
jp9000 已提交
544
		encoder->media : NULL;
545 546
}

547
audio_t *obs_encoder_audio(const obs_encoder_t *encoder)
548 549
{
	return (encoder && encoder->info.type == OBS_ENCODER_AUDIO) ?
J
jp9000 已提交
550
		encoder->media : NULL;
551 552
}

553
bool obs_encoder_active(const obs_encoder_t *encoder)
554 555 556 557
{
	return encoder ? encoder->active : false;
}

558
static inline bool get_sei(const struct obs_encoder *encoder,
559 560
		uint8_t **sei, size_t *size)
{
561 562 563
	if (encoder->info.get_sei_data)
		return encoder->info.get_sei_data(encoder->context.data, sei,
				size);
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
	return false;
}

static void send_first_video_packet(struct obs_encoder *encoder,
		struct encoder_callback *cb, struct encoder_packet *packet)
{
	struct encoder_packet first_packet;
	DARRAY(uint8_t)       data;
	uint8_t               *sei;
	size_t                size;

	/* always wait for first keyframe */
	if (!packet->keyframe)
		return;

	da_init(data);

	if (!get_sei(encoder, &sei, &size)) {
		cb->new_packet(cb->param, packet);
J
jp9000 已提交
583
		cb->sent_first_packet = true;
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
		return;
	}

	da_push_back_array(data, sei, size);
	da_push_back_array(data, packet->data, packet->size);

	first_packet      = *packet;
	first_packet.data = data.array;
	first_packet.size = data.num;

	cb->new_packet(cb->param, &first_packet);
	cb->sent_first_packet = true;

	da_free(data);
}

static inline void send_packet(struct obs_encoder *encoder,
		struct encoder_callback *cb, struct encoder_packet *packet)
{
	/* include SEI in first video packet */
	if (encoder->info.type == OBS_ENCODER_VIDEO && !cb->sent_first_packet)
		send_first_video_packet(encoder, cb, packet);
	else
		cb->new_packet(cb->param, packet);
}

J
jp9000 已提交
610 611 612 613 614 615 616 617 618 619
static void full_stop(struct obs_encoder *encoder)
{
	if (encoder) {
		pthread_mutex_lock(&encoder->callbacks_mutex);
		da_free(encoder->callbacks);
		remove_connection(encoder);
		pthread_mutex_unlock(&encoder->callbacks_mutex);
	}
}

P
Palana 已提交
620
static const char *do_encode_name = "do_encode";
621
static inline void do_encode(struct obs_encoder *encoder,
622
		struct encoder_frame *frame)
623
{
P
Palana 已提交
624 625 626 627 628 629
	profile_start(do_encode_name);
	if (!encoder->profile_encoder_encode_name)
		encoder->profile_encoder_encode_name =
			profile_store_name(obs_get_profiler_name_store(),
					"encode(%s)", encoder->context.name);

630
	struct encoder_packet pkt = {0};
631 632 633
	bool received = false;
	bool success;

634 635
	pkt.timebase_num = encoder->timebase_num;
	pkt.timebase_den = encoder->timebase_den;
636
	pkt.encoder = encoder;
637

P
Palana 已提交
638
	profile_start(encoder->profile_encoder_encode_name);
639 640
	success = encoder->info.encode(encoder->context.data, frame, &pkt,
			&received);
P
Palana 已提交
641
	profile_end(encoder->profile_encoder_encode_name);
642 643 644
	if (!success) {
		full_stop(encoder);
		blog(LOG_ERROR, "Error encoding with encoder '%s'",
645
				encoder->context.name);
646 647 648 649
		return;
	}

	if (received) {
650 651 652 653
		/* we use system time here to ensure sync with other encoders,
		 * you do not want to use relative timestamps here */
		pkt.dts_usec = encoder->start_ts / 1000 + packet_dts_usec(&pkt);

654 655
		pthread_mutex_lock(&encoder->callbacks_mutex);

656
		for (size_t i = encoder->callbacks.num; i > 0; i--) {
657
			struct encoder_callback *cb;
658
			cb = encoder->callbacks.array+(i-1);
659
			send_packet(encoder, cb, &pkt);
660 661 662 663
		}

		pthread_mutex_unlock(&encoder->callbacks_mutex);
	}
P
Palana 已提交
664 665

	profile_end(do_encode_name);
666 667
}

P
Palana 已提交
668
static const char *receive_video_name = "receive_video";
669 670
static void receive_video(void *param, struct video_data *frame)
{
P
Palana 已提交
671 672
	profile_start(receive_video_name);

673 674 675 676 677 678 679 680 681 682
	struct obs_encoder    *encoder  = param;
	struct encoder_frame  enc_frame;

	memset(&enc_frame, 0, sizeof(struct encoder_frame));

	for (size_t i = 0; i < MAX_AV_PLANES; i++) {
		enc_frame.data[i]     = frame->data[i];
		enc_frame.linesize[i] = frame->linesize[i];
	}

683 684 685
	if (!encoder->start_ts)
		encoder->start_ts = frame->timestamp;

686 687 688
	enc_frame.frames = 1;
	enc_frame.pts    = encoder->cur_pts;

689
	do_encode(encoder, &enc_frame);
690 691

	encoder->cur_pts += encoder->timebase_num;
P
Palana 已提交
692 693

	profile_end(receive_video_name);
694 695
}

P
Palana 已提交
696
static const char *buffer_audio_name = "buffer_audio";
697 698
static bool buffer_audio(struct obs_encoder *encoder, struct audio_data *data)
{
P
Palana 已提交
699 700
	profile_start(buffer_audio_name);

701 702 703 704
	size_t samplerate = encoder->samplerate;
	size_t size = data->frames * encoder->blocksize;
	size_t offset_size = 0;

705
	if (!encoder->start_ts && encoder->paired_encoder) {
706 707 708 709 710
		uint64_t end_ts     = data->timestamp;
		uint64_t v_start_ts = encoder->paired_encoder->start_ts;

		/* no video yet, so don't start audio */
		if (!v_start_ts)
P
Palana 已提交
711
			goto fail;
712 713 714 715 716

		/* audio starting point still not synced with video starting
		 * point, so don't start audio */
		end_ts += (uint64_t)data->frames * 1000000000ULL / samplerate;
		if (end_ts <= v_start_ts)
P
Palana 已提交
717
			goto fail;
718 719 720 721 722 723 724 725 726

		/* ready to start audio, truncate if necessary */
		if (data->timestamp < v_start_ts) {
			uint64_t offset = v_start_ts - data->timestamp;
			offset = (int)(offset * samplerate / 1000000000);
			offset_size = (size_t)offset * encoder->blocksize;
		}

		encoder->start_ts = v_start_ts;
727 728 729

	} else if (!encoder->start_ts && !encoder->paired_encoder) {
		encoder->start_ts = data->timestamp;
730 731 732 733 734 735 736 737 738 739
	}

	size -= offset_size;

	/* push in to the circular buffer */
	if (size)
		for (size_t i = 0; i < encoder->planes; i++)
			circlebuf_push_back(&encoder->audio_input_buffer[i],
					data->data[i] + offset_size, size);

P
Palana 已提交
740
	profile_end(buffer_audio_name);
741
	return true;
P
Palana 已提交
742 743 744 745

fail:
	profile_end(buffer_audio_name);
	return false;
746 747 748
}

static void send_audio_data(struct obs_encoder *encoder)
749 750 751 752 753
{
	struct encoder_frame  enc_frame;

	memset(&enc_frame, 0, sizeof(struct encoder_frame));

754 755 756 757
	for (size_t i = 0; i < encoder->planes; i++) {
		circlebuf_pop_front(&encoder->audio_input_buffer[i],
				encoder->audio_output_buffer[i],
				encoder->framesize_bytes);
758

759 760
		enc_frame.data[i]     = encoder->audio_output_buffer[i];
		enc_frame.linesize[i] = (uint32_t)encoder->framesize_bytes;
761 762
	}

763
	enc_frame.frames = (uint32_t)encoder->framesize;
764 765
	enc_frame.pts    = encoder->cur_pts;

766 767 768 769 770
	do_encode(encoder, &enc_frame);

	encoder->cur_pts += encoder->framesize;
}

P
Palana 已提交
771
static const char *receive_audio_name = "receive_audio";
772
static void receive_audio(void *param, size_t mix_idx, struct audio_data *data)
773
{
P
Palana 已提交
774 775
	profile_start(receive_audio_name);

776 777 778
	struct obs_encoder *encoder = param;

	if (!buffer_audio(encoder, data))
P
Palana 已提交
779
		goto end;
780

781 782
	while (encoder->audio_input_buffer[0].size >= encoder->framesize_bytes)
		send_audio_data(encoder);
783 784

	UNUSED_PARAMETER(mix_idx);
P
Palana 已提交
785 786 787

end:
	profile_end(receive_audio_name);
788
}
J
jp9000 已提交
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808

void obs_encoder_add_output(struct obs_encoder *encoder,
		struct obs_output *output)
{
	if (!encoder) return;

	pthread_mutex_lock(&encoder->outputs_mutex);
	da_push_back(encoder->outputs, &output);
	pthread_mutex_unlock(&encoder->outputs_mutex);
}

void obs_encoder_remove_output(struct obs_encoder *encoder,
		struct obs_output *output)
{
	if (!encoder) return;

	pthread_mutex_lock(&encoder->outputs_mutex);
	da_erase_item(encoder->outputs, &output);
	pthread_mutex_unlock(&encoder->outputs_mutex);
}
809 810 811 812 813 814 815 816 817 818 819 820 821

void obs_duplicate_encoder_packet(struct encoder_packet *dst,
		const struct encoder_packet *src)
{
	*dst = *src;
	dst->data = bmemdup(src->data, src->size);
}

void obs_free_encoder_packet(struct encoder_packet *packet)
{
	bfree(packet->data);
	memset(packet, 0, sizeof(struct encoder_packet));
}
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839

void obs_encoder_set_preferred_video_format(obs_encoder_t *encoder,
		enum video_format format)
{
	if (!encoder || encoder->info.type != OBS_ENCODER_VIDEO)
		return;

	encoder->preferred_format = format;
}

enum video_format obs_encoder_get_preferred_video_format(
		const obs_encoder_t *encoder)
{
	if (!encoder || encoder->info.type != OBS_ENCODER_VIDEO)
		return VIDEO_FORMAT_NONE;

	return encoder->preferred_format;
}
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914

void obs_encoder_addref(obs_encoder_t *encoder)
{
	if (!encoder)
		return;

	obs_ref_addref(&encoder->control->ref);
}

void obs_encoder_release(obs_encoder_t *encoder)
{
	if (!encoder)
		return;

	obs_weak_encoder_t *control = encoder->control;
	if (obs_ref_release(&control->ref)) {
		// The order of operations is important here since
		// get_context_by_name in obs.c relies on weak refs
		// being alive while the context is listed
		obs_encoder_destroy(encoder);
		obs_weak_encoder_release(control);
	}
}

void obs_weak_encoder_addref(obs_weak_encoder_t *weak)
{
	if (!weak)
		return;

	obs_weak_ref_addref(&weak->ref);
}

void obs_weak_encoder_release(obs_weak_encoder_t *weak)
{
	if (!weak)
		return;

	if (obs_weak_ref_release(&weak->ref))
		bfree(weak);
}

obs_encoder_t *obs_encoder_get_ref(obs_encoder_t *encoder)
{
	if (!encoder)
		return NULL;

	return obs_weak_encoder_get_encoder(encoder->control);
}

obs_weak_encoder_t *obs_encoder_get_weak_encoder(obs_encoder_t *encoder)
{
	if (!encoder)
		return NULL;

	obs_weak_encoder_t *weak = encoder->control;
	obs_weak_encoder_addref(weak);
	return weak;
}

obs_encoder_t *obs_weak_encoder_get_encoder(obs_weak_encoder_t *weak)
{
	if (!weak)
		return NULL;

	if (obs_weak_ref_get_ref(&weak->ref))
		return weak->encoder;

	return NULL;
}

bool obs_weak_encoder_references_encoder(obs_weak_encoder_t *weak,
		obs_encoder_t *encoder)
{
	return weak && encoder && weak->encoder == encoder;
}