| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 | 
							- /******************************************************************************
 
-     Copyright (C) 2014 by Hugh Bailey <[email protected]>
 
-     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 <stdio.h>
 
- #include <obs.h>
 
- #include <obs-avc.h>
 
- #include <util/platform.h>
 
- #include <util/dstr.h>
 
- #include <util/threading.h>
 
- #include <inttypes.h>
 
- #include "flv-mux.h"
 
- struct flv_output {
 
- 	obs_output_t output;
 
- 	struct dstr  path;
 
- 	FILE         *file;
 
- 	bool         active;
 
- 	int64_t      last_packet_ts;
 
- };
 
- static const char *flv_output_getname(const char *locale)
 
- {
 
- 	UNUSED_PARAMETER(locale);
 
- 	return "FLV File Output";
 
- }
 
- static void flv_output_stop(void *data);
 
- static void flv_output_destroy(void *data)
 
- {
 
- 	struct flv_output *stream = data;
 
- 	if (stream->active)
 
- 		flv_output_stop(data);
 
- 	dstr_free(&stream->path);
 
- 	bfree(stream);
 
- }
 
- static void *flv_output_create(obs_data_t settings, obs_output_t output)
 
- {
 
- 	struct flv_output *stream = bzalloc(sizeof(struct flv_output));
 
- 	stream->output = output;
 
- 	UNUSED_PARAMETER(settings);
 
- 	return stream;
 
- }
 
- static void flv_output_stop(void *data)
 
- {
 
- 	struct flv_output *stream = data;
 
- 	if (stream->active) {
 
- 		if (stream->file)
 
- 			write_file_info(stream->file, stream->last_packet_ts,
 
- 					os_ftelli64(stream->file));
 
- 		fclose(stream->file);
 
- 		obs_output_end_data_capture(stream->output);
 
- 		stream->active = false;
 
- 	}
 
- }
 
- static int write_packet(struct flv_output *stream,
 
- 		struct encoder_packet *packet, bool is_header)
 
- {
 
- 	uint8_t *data;
 
- 	size_t  size;
 
- 	int     ret = 0;
 
- 	stream->last_packet_ts = get_ms_time(packet, packet->dts);
 
- 	flv_packet_mux(packet, &data, &size, is_header);
 
- 	fwrite(data, 1, size, stream->file);
 
- 	bfree(data);
 
- 	obs_free_encoder_packet(packet);
 
- 	return ret;
 
- }
 
- static void write_meta_data(struct flv_output *stream)
 
- {
 
- 	uint8_t *meta_data;
 
- 	size_t  meta_data_size;
 
- 	flv_meta_data(stream->output, &meta_data, &meta_data_size, true);
 
- 	fwrite(meta_data, 1, meta_data_size, stream->file);
 
- 	bfree(meta_data);
 
- }
 
- static void write_audio_header(struct flv_output *stream)
 
- {
 
- 	obs_output_t  context  = stream->output;
 
- 	obs_encoder_t aencoder = obs_output_get_audio_encoder(context);
 
- 	uint8_t       *header;
 
- 	struct encoder_packet packet   = {
 
- 		.type         = OBS_ENCODER_AUDIO,
 
- 		.timebase_den = 1
 
- 	};
 
- 	obs_encoder_get_extra_data(aencoder, &header, &packet.size);
 
- 	packet.data = bmemdup(header, packet.size);
 
- 	write_packet(stream, &packet, true);
 
- }
 
- static void write_video_header(struct flv_output *stream)
 
- {
 
- 	obs_output_t  context  = stream->output;
 
- 	obs_encoder_t vencoder = obs_output_get_video_encoder(context);
 
- 	uint8_t       *header;
 
- 	size_t        size;
 
- 	struct encoder_packet packet   = {
 
- 		.type         = OBS_ENCODER_VIDEO,
 
- 		.timebase_den = 1,
 
- 		.keyframe     = true
 
- 	};
 
- 	obs_encoder_get_extra_data(vencoder, &header, &size);
 
- 	packet.size = obs_parse_avc_header(&packet.data, header, size);
 
- 	write_packet(stream, &packet, true);
 
- }
 
- static void write_headers(struct flv_output *stream)
 
- {
 
- 	write_meta_data(stream);
 
- 	write_audio_header(stream);
 
- 	write_video_header(stream);
 
- }
 
- static bool flv_output_start(void *data)
 
- {
 
- 	struct flv_output *stream = data;
 
- 	obs_data_t settings;
 
- 	const char *path;
 
- 	if (!obs_output_can_begin_data_capture(stream->output, 0))
 
- 		return false;
 
- 	if (!obs_output_initialize_encoders(stream->output, 0))
 
- 		return false;
 
- 	/* get path */
 
- 	settings = obs_output_get_settings(stream->output);
 
- 	path = obs_data_getstring(settings, "path");
 
- 	dstr_copy(&stream->path, path);
 
- 	obs_data_release(settings);
 
- 	stream->file = os_fopen(stream->path.array, "wb");
 
- 	if (!stream->file) {
 
- 		blog(LOG_WARNING, "Unable to open FLV file '%s'",
 
- 				stream->path.array);
 
- 		return false;
 
- 	}
 
- 	/* write headers and start capture */
 
- 	stream->active = true;
 
- 	write_headers(stream);
 
- 	obs_output_begin_data_capture(stream->output, 0);
 
- 	return true;
 
- }
 
- static void flv_output_data(void *data, struct encoder_packet *packet)
 
- {
 
- 	struct flv_output     *stream = data;
 
- 	struct encoder_packet parsed_packet;
 
- 	if (packet->type == OBS_ENCODER_VIDEO) {
 
- 		obs_parse_avc_packet(&parsed_packet, packet);
 
- 		write_packet(stream, &parsed_packet, false);
 
- 		obs_free_encoder_packet(&parsed_packet);
 
- 	} else {
 
- 		write_packet(stream, packet, false);
 
- 	}
 
- }
 
- static obs_properties_t flv_output_properties(const char *locale)
 
- {
 
- 	obs_properties_t props = obs_properties_create(locale);
 
- 	/* TODO: locale */
 
- 	obs_properties_add_text(props, "path", "File Path", OBS_TEXT_DEFAULT);
 
- 	return props;
 
- }
 
- struct obs_output_info flv_output_info = {
 
- 	.id             = "flv_output",
 
- 	.flags          = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED,
 
- 	.getname        = flv_output_getname,
 
- 	.create         = flv_output_create,
 
- 	.destroy        = flv_output_destroy,
 
- 	.start          = flv_output_start,
 
- 	.stop           = flv_output_stop,
 
- 	.encoded_packet = flv_output_data,
 
- 	.properties     = flv_output_properties
 
- };
 
 
  |