|
|
@@ -31,6 +31,7 @@
|
|
|
|
|
|
#define AUDIODATA_AAC 10.0
|
|
|
|
|
|
+#define AUDIO_FRAMETYPE_OFFSET 4
|
|
|
#define VIDEO_FRAMETYPE_OFFSET 4
|
|
|
|
|
|
enum video_frametype_t {
|
|
|
@@ -39,6 +40,14 @@ enum video_frametype_t {
|
|
|
};
|
|
|
|
|
|
// Y2023 spec
|
|
|
+const uint8_t AUDIO_HEADER_EX = 9 << AUDIO_FRAMETYPE_OFFSET;
|
|
|
+enum audio_packet_type_t {
|
|
|
+ AUDIO_PACKETTYPE_SEQ_START = 0,
|
|
|
+ AUDIO_PACKETTYPE_FRAMES = 1,
|
|
|
+ AUDIO_PACKETTYPE_MULTICHANNEL_CONFIG = 4,
|
|
|
+ AUDIO_PACKETTYPE_MULTITRACK = 5,
|
|
|
+};
|
|
|
+
|
|
|
const uint8_t FRAME_HEADER_EX = 8 << VIDEO_FRAMETYPE_OFFSET;
|
|
|
enum packet_type_t {
|
|
|
PACKETTYPE_SEQ_START = 0,
|
|
|
@@ -63,6 +72,22 @@ enum datatype_t {
|
|
|
DATA_TYPE_OBJECT_END = 9,
|
|
|
};
|
|
|
|
|
|
+static void s_wa4cc(struct serializer *s, enum audio_id_t id)
|
|
|
+{
|
|
|
+ switch (id) {
|
|
|
+ case AUDIO_CODEC_NONE:
|
|
|
+ assert(0 && "Tried to serialize AUDIO_CODEC_NONE");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AUDIO_CODEC_AAC:
|
|
|
+ s_w8(s, 'm');
|
|
|
+ s_w8(s, 'p');
|
|
|
+ s_w8(s, '4');
|
|
|
+ s_w8(s, 'a');
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void s_w4cc(struct serializer *s, enum video_id_t id)
|
|
|
{
|
|
|
switch (id) {
|
|
|
@@ -376,6 +401,62 @@ void flv_packet_mux(struct encoder_packet *packet, int32_t dts_offset,
|
|
|
*size = data.bytes.num;
|
|
|
}
|
|
|
|
|
|
+void flv_packet_audio_ex(struct encoder_packet *packet,
|
|
|
+ enum audio_id_t codec_id, int32_t dts_offset,
|
|
|
+ uint8_t **output, size_t *size, int type, size_t idx)
|
|
|
+{
|
|
|
+ struct array_output_data data;
|
|
|
+ struct serializer s;
|
|
|
+
|
|
|
+ array_output_serializer_init(&s, &data);
|
|
|
+
|
|
|
+ assert(packet->type == OBS_ENCODER_AUDIO);
|
|
|
+
|
|
|
+ int32_t time_ms = get_ms_time(packet, packet->dts) - dts_offset;
|
|
|
+
|
|
|
+ bool is_multitrack = idx > 0;
|
|
|
+
|
|
|
+ if (!packet->data || !packet->size)
|
|
|
+ return;
|
|
|
+
|
|
|
+ int header_metadata_size = 5; // w8+wa4cc
|
|
|
+ if (is_multitrack)
|
|
|
+ header_metadata_size += 2; // w8 + w8
|
|
|
+
|
|
|
+ s_w8(&s, RTMP_PACKET_TYPE_AUDIO);
|
|
|
+
|
|
|
+#ifdef DEBUG_TIMESTAMPS
|
|
|
+ blog(LOG_DEBUG, "Audio: %lu", time_ms);
|
|
|
+
|
|
|
+ if (last_time > time_ms)
|
|
|
+ blog(LOG_DEBUG, "Non-monotonic");
|
|
|
+
|
|
|
+ last_time = time_ms;
|
|
|
+#endif
|
|
|
+
|
|
|
+ s_wb24(&s, (uint32_t)packet->size + header_metadata_size);
|
|
|
+ s_wb24(&s, (uint32_t)time_ms);
|
|
|
+ s_w8(&s, (time_ms >> 24) & 0x7F);
|
|
|
+ s_wb24(&s, 0);
|
|
|
+
|
|
|
+ s_w8(&s, AUDIO_HEADER_EX |
|
|
|
+ (is_multitrack ? AUDIO_PACKETTYPE_MULTITRACK : type));
|
|
|
+ if (is_multitrack) {
|
|
|
+ s_w8(&s, MULTITRACKTYPE_ONE_TRACK | type);
|
|
|
+ s_wa4cc(&s, codec_id);
|
|
|
+ s_w8(&s, (uint8_t)idx);
|
|
|
+ } else {
|
|
|
+ s_wa4cc(&s, codec_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ s_write(&s, packet->data, packet->size);
|
|
|
+
|
|
|
+ write_previous_tag_size(&s);
|
|
|
+
|
|
|
+ *output = data.bytes.array;
|
|
|
+ *size = data.bytes.num;
|
|
|
+}
|
|
|
+
|
|
|
// Y2023 spec
|
|
|
void flv_packet_ex(struct encoder_packet *packet, enum video_id_t codec_id,
|
|
|
int32_t dts_offset, uint8_t **output, size_t *size, int type,
|
|
|
@@ -466,6 +547,22 @@ void flv_packet_end(struct encoder_packet *packet, enum video_id_t codec,
|
|
|
flv_packet_ex(packet, codec, 0, output, size, PACKETTYPE_SEQ_END, idx);
|
|
|
}
|
|
|
|
|
|
+void flv_packet_audio_start(struct encoder_packet *packet,
|
|
|
+ enum audio_id_t codec, uint8_t **output,
|
|
|
+ size_t *size, size_t idx)
|
|
|
+{
|
|
|
+ flv_packet_audio_ex(packet, codec, 0, output, size,
|
|
|
+ AUDIO_PACKETTYPE_SEQ_START, idx);
|
|
|
+}
|
|
|
+
|
|
|
+void flv_packet_audio_frames(struct encoder_packet *packet,
|
|
|
+ enum audio_id_t codec, int32_t dts_offset,
|
|
|
+ uint8_t **output, size_t *size, size_t idx)
|
|
|
+{
|
|
|
+ flv_packet_audio_ex(packet, codec, dts_offset, output, size,
|
|
|
+ AUDIO_PACKETTYPE_FRAMES, idx);
|
|
|
+}
|
|
|
+
|
|
|
void flv_packet_metadata(enum video_id_t codec_id, uint8_t **output,
|
|
|
size_t *size, int bits_per_raw_sample,
|
|
|
uint8_t color_primaries, int color_trc,
|