2014-04-01 11:55:18 -07:00
|
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2014 by Hugh Bailey <obs.jim@gmail.com>
|
|
|
|
|
|
|
|
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>
|
2014-05-16 00:18:23 -07:00
|
|
|
#include <stdio.h>
|
2014-07-01 13:11:15 -07:00
|
|
|
#include <util/dstr.h>
|
2014-04-01 11:55:18 -07:00
|
|
|
#include <util/array-serializer.h>
|
|
|
|
#include "flv-mux.h"
|
|
|
|
#include "obs-output-ver.h"
|
|
|
|
#include "rtmp-helpers.h"
|
|
|
|
|
2014-04-10 11:59:42 -07:00
|
|
|
/* TODO: FIXME: this is currently hard-coded to h264 and aac! ..not that we'll
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
* use anything else for a long time. */
|
|
|
|
|
2014-04-10 11:59:42 -07:00
|
|
|
//#define DEBUG_TIMESTAMPS
|
|
|
|
//#define WRITE_FLV_HEADER
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
#define VIDEO_HEADER_SIZE 5
|
|
|
|
|
|
|
|
static inline double encoder_bitrate(obs_encoder_t encoder)
|
|
|
|
{
|
|
|
|
obs_data_t settings = obs_encoder_get_settings(encoder);
|
2014-08-05 11:09:29 -07:00
|
|
|
double bitrate = obs_data_get_double(settings, "bitrate");
|
2014-04-01 11:55:18 -07:00
|
|
|
|
|
|
|
obs_data_release(settings);
|
|
|
|
return bitrate;
|
|
|
|
}
|
|
|
|
|
2014-05-16 00:18:23 -07:00
|
|
|
#define FLV_INFO_SIZE_OFFSET 42
|
|
|
|
|
|
|
|
void write_file_info(FILE *file, int64_t duration_ms, int64_t size)
|
|
|
|
{
|
|
|
|
char buf[64];
|
|
|
|
char *enc = buf;
|
|
|
|
char *end = enc + sizeof(buf);
|
|
|
|
|
|
|
|
fseek(file, FLV_INFO_SIZE_OFFSET, SEEK_SET);
|
|
|
|
|
|
|
|
enc_num_val(&enc, end, "duration", (double)duration_ms / 1000.0);
|
|
|
|
enc_num_val(&enc, end, "fileSize", (double)size);
|
|
|
|
|
|
|
|
fwrite(buf, 1, enc - buf, file);
|
|
|
|
}
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
static void build_flv_meta_data(obs_output_t context,
|
|
|
|
uint8_t **output, size_t *size)
|
|
|
|
{
|
|
|
|
obs_encoder_t vencoder = obs_output_get_video_encoder(context);
|
|
|
|
obs_encoder_t aencoder = obs_output_get_audio_encoder(context);
|
|
|
|
video_t video = obs_encoder_video(vencoder);
|
|
|
|
audio_t audio = obs_encoder_audio(aencoder);
|
|
|
|
char buf[4096];
|
|
|
|
char *enc = buf;
|
|
|
|
char *end = enc+sizeof(buf);
|
2014-07-01 13:11:15 -07:00
|
|
|
struct dstr encoder_name = {0};
|
2014-04-01 11:55:18 -07:00
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
enc_str(&enc, end, "onMetaData");
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
*enc++ = AMF_ECMA_ARRAY;
|
|
|
|
enc = AMF_EncodeInt32(enc, end, 14);
|
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
enc_num_val(&enc, end, "duration", 0.0);
|
|
|
|
enc_num_val(&enc, end, "fileSize", 0.0);
|
2014-04-01 11:55:18 -07:00
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
enc_num_val(&enc, end, "width", (double)video_output_width(video));
|
|
|
|
enc_num_val(&enc, end, "height", (double)video_output_height(video));
|
|
|
|
enc_str_val(&enc, end, "videocodecid", "avc1");
|
|
|
|
enc_num_val(&enc, end, "videodatarate", encoder_bitrate(vencoder));
|
|
|
|
enc_num_val(&enc, end, "framerate", video_output_framerate(video));
|
2014-04-01 11:55:18 -07:00
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
enc_str_val(&enc, end, "audiocodecid", "mp4a");
|
|
|
|
enc_num_val(&enc, end, "audiodatarate", encoder_bitrate(aencoder));
|
|
|
|
enc_num_val(&enc, end, "audiosamplerate",
|
2014-04-01 11:55:18 -07:00
|
|
|
(double)audio_output_samplerate(audio));
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
enc_num_val(&enc, end, "audiosamplesize", 16.0);
|
|
|
|
enc_num_val(&enc, end, "audiochannels",
|
2014-04-01 11:55:18 -07:00
|
|
|
(double)audio_output_channels(audio));
|
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
enc_bool_val(&enc, end, "stereo", audio_output_channels(audio) == 2);
|
2014-07-01 13:11:15 -07:00
|
|
|
|
2014-07-14 09:52:36 -07:00
|
|
|
dstr_printf(&encoder_name, "%s (libobs version ",
|
|
|
|
MODULE_NAME);
|
|
|
|
|
|
|
|
#ifdef HAVE_OBSCONFIG_H
|
|
|
|
dstr_cat(&encoder_name, OBS_VERSION);
|
|
|
|
#else
|
|
|
|
dstr_catf(&encoder_name, "%d.%d.%d",
|
2014-07-01 13:11:15 -07:00
|
|
|
LIBOBS_API_MAJOR_VER,
|
|
|
|
LIBOBS_API_MINOR_VER,
|
|
|
|
LIBOBS_API_PATCH_VER);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dstr_cat(&encoder_name, ")");
|
|
|
|
|
|
|
|
enc_str_val(&enc, end, "encoder", encoder_name.array);
|
|
|
|
dstr_free(&encoder_name);
|
2014-04-01 11:55:18 -07:00
|
|
|
|
|
|
|
*enc++ = 0;
|
|
|
|
*enc++ = 0;
|
|
|
|
*enc++ = AMF_OBJECT_END;
|
|
|
|
|
|
|
|
*size = enc-buf;
|
|
|
|
*output = bmemdup(buf, *size);
|
|
|
|
}
|
|
|
|
|
2014-05-16 00:18:23 -07:00
|
|
|
void flv_meta_data(obs_output_t context, uint8_t **output, size_t *size,
|
|
|
|
bool write_header)
|
2014-04-01 11:55:18 -07:00
|
|
|
{
|
|
|
|
struct array_output_data data;
|
|
|
|
struct serializer s;
|
|
|
|
uint8_t *meta_data;
|
|
|
|
size_t meta_data_size;
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
uint32_t start_pos;
|
2014-04-01 11:55:18 -07:00
|
|
|
|
2014-04-02 00:42:12 -07:00
|
|
|
array_output_serializer_init(&s, &data);
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
build_flv_meta_data(context, &meta_data, &meta_data_size);
|
|
|
|
|
2014-05-16 00:18:23 -07:00
|
|
|
if (write_header) {
|
|
|
|
s_write(&s, "FLV", 3);
|
|
|
|
s_w8(&s, 1);
|
|
|
|
s_w8(&s, 5);
|
|
|
|
s_wb32(&s, 9);
|
|
|
|
s_wb32(&s, 0);
|
|
|
|
}
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
|
|
|
|
start_pos = serializer_get_pos(&s);
|
|
|
|
|
2014-04-02 00:42:12 -07:00
|
|
|
s_w8(&s, RTMP_PACKET_TYPE_INFO);
|
2014-04-01 11:55:18 -07:00
|
|
|
|
|
|
|
s_wb24(&s, (uint32_t)meta_data_size);
|
|
|
|
s_wb32(&s, 0);
|
|
|
|
s_wb24(&s, 0);
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
s_write(&s, meta_data, meta_data_size);
|
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
s_wb32(&s, (uint32_t)serializer_get_pos(&s) - start_pos + 4 - 1);
|
2014-04-01 11:55:18 -07:00
|
|
|
|
|
|
|
*output = data.bytes.array;
|
|
|
|
*size = data.bytes.num;
|
|
|
|
|
|
|
|
bfree(meta_data);
|
|
|
|
}
|
|
|
|
|
2014-04-14 02:02:59 -07:00
|
|
|
#ifdef DEBUG_TIMESTAMPS
|
|
|
|
static int32_t last_time = 0;
|
|
|
|
#endif
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
static void flv_video(struct serializer *s, struct encoder_packet *packet,
|
|
|
|
bool is_header)
|
|
|
|
{
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
int64_t offset = packet->pts - packet->dts;
|
|
|
|
int32_t time_ms = get_ms_time(packet, packet->dts);
|
2014-04-01 11:55:18 -07:00
|
|
|
|
|
|
|
if (!packet->data || !packet->size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
s_w8(s, RTMP_PACKET_TYPE_VIDEO);
|
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
#ifdef DEBUG_TIMESTAMPS
|
|
|
|
blog(LOG_DEBUG, "Video: %lu", time_ms);
|
2014-04-14 02:02:59 -07:00
|
|
|
|
|
|
|
if (last_time > time_ms)
|
|
|
|
blog(LOG_DEBUG, "Non-monotonic");
|
|
|
|
|
|
|
|
last_time = time_ms;
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
#endif
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
s_wb24(s, (uint32_t)packet->size + 5);
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
s_wb24(s, time_ms);
|
|
|
|
s_w8(s, (time_ms >> 24) & 0x7F);
|
2014-04-01 11:55:18 -07:00
|
|
|
s_wb24(s, 0);
|
|
|
|
|
|
|
|
/* these are the 5 extra bytes mentioned above */
|
|
|
|
s_w8(s, packet->keyframe ? 0x17 : 0x27);
|
|
|
|
s_w8(s, is_header ? 0 : 1);
|
|
|
|
s_wb24(s, get_ms_time(packet, offset));
|
|
|
|
s_write(s, packet->data, packet->size);
|
|
|
|
|
|
|
|
/* write tag size (starting byte doesnt count) */
|
|
|
|
s_wb32(s, (uint32_t)serializer_get_pos(s) + 4 - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flv_audio(struct serializer *s, struct encoder_packet *packet,
|
|
|
|
bool is_header)
|
|
|
|
{
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
int32_t time_ms = get_ms_time(packet, packet->dts);
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
if (!packet->data || !packet->size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
s_w8(s, RTMP_PACKET_TYPE_AUDIO);
|
|
|
|
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
#ifdef DEBUG_TIMESTAMPS
|
|
|
|
blog(LOG_DEBUG, "Audio: %lu", time_ms);
|
2014-04-14 02:02:59 -07:00
|
|
|
|
|
|
|
if (last_time > time_ms)
|
|
|
|
blog(LOG_DEBUG, "Non-monotonic");
|
|
|
|
|
|
|
|
last_time = time_ms;
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
#endif
|
|
|
|
|
2014-04-01 11:55:18 -07:00
|
|
|
s_wb24(s, (uint32_t)packet->size + 2);
|
Implement RTMP module (still needs drop code)
- Implement the RTMP output module. This time around, we just use a
simple FLV muxer, then just write to the stream with RTMP_Write.
Easy and effective.
- Fix the FLV muxer, the muxer now outputs proper FLV packets.
- Output API:
* When using encoders, automatically interleave encoded packets
before sending it to the output.
* Pair encoders and have them automatically wait for the other to
start to ensure sync.
* Change 'obs_output_signal_start_fail' to 'obs_output_signal_stop'
because it was a bit confusing, and doing this makes a lot more
sense for outputs that need to stop suddenly (disconnections/etc).
- Encoder API:
* Remove some unnecessary encoder functions from the actual API and
make them internal. Most of the encoder functions are handled
automatically by outputs anyway, so there's no real need to expose
them and end up inadvertently confusing plugin writers.
* Have audio encoders wait for the video encoder to get a frame, then
start at the exact data point that the first video frame starts to
ensure the most accrate sync of video/audio possible.
* Add a required 'frame_size' callback for audio encoders that
returns the expected number of frames desired to encode with. This
way, the libobs encoder API can handle the circular buffering
internally automatically for the encoder modules, so encoder
writers don't have to do it themselves.
- Fix a few bugs in the serializer interface. It was passing the wrong
variable for the data in a few cases.
- If a source has video, make obs_source_update defer the actual update
callback until the tick function is called to prevent threading
issues.
2014-04-07 22:00:10 -07:00
|
|
|
s_wb24(s, time_ms);
|
|
|
|
s_w8(s, (time_ms >> 24) & 0x7F);
|
2014-04-01 11:55:18 -07:00
|
|
|
s_wb24(s, 0);
|
|
|
|
|
|
|
|
/* these are the two extra bytes mentioned above */
|
|
|
|
s_w8(s, 0xaf);
|
|
|
|
s_w8(s, is_header ? 0 : 1);
|
|
|
|
s_write(s, packet->data, packet->size);
|
|
|
|
|
|
|
|
/* write tag size (starting byte doesnt count) */
|
|
|
|
s_wb32(s, (uint32_t)serializer_get_pos(s) + 4 - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void flv_packet_mux(struct encoder_packet *packet,
|
|
|
|
uint8_t **output, size_t *size, bool is_header)
|
|
|
|
{
|
|
|
|
struct array_output_data data;
|
|
|
|
struct serializer s;
|
|
|
|
|
|
|
|
array_output_serializer_init(&s, &data);
|
|
|
|
|
|
|
|
if (packet->type == OBS_ENCODER_VIDEO)
|
|
|
|
flv_video(&s, packet, is_header);
|
|
|
|
else
|
|
|
|
flv_audio(&s, packet, is_header);
|
|
|
|
|
|
|
|
*output = data.bytes.array;
|
|
|
|
*size = data.bytes.num;
|
|
|
|
}
|