1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#include "decoder.h"
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/audio_fifo.h>
#include <libavutil/channel_layout.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
#include <glib.h>
#include <stdint.h>
#include <libavutil/opt.h>
#include "types.h"
#include "log.h"
#include "str.h"
#include "output.h"
#include "mix.h"
#include "resample.h"
#include "codeclib.h"
#include "streambuf.h"
#include "main.h"
#include "packet.h"
#include "tag.h"
#include "tls_send.h"
// does not initialise the contained `sink`
decode_t *decoder_new(const char *payload_str, const char *format, int ptime) {
char *slash = strchr(payload_str, '/');
if (!slash) {
ilog(LOG_WARN, "Invalid payload format: %s", payload_str);
return NULL;
}
str name = STR_LEN(payload_str, slash - payload_str);
int clockrate = atoi(slash + 1);
if (clockrate <= 0) {
ilog(LOG_ERR, "Invalid clock rate %i (parsed from '%.20s'/'%.20s')",
clockrate, slash + 1, payload_str);
return NULL;
}
int channels = 1;
slash = strchr(slash + 1, '/');
if (slash) {
channels = atoi(slash + 1);
if (!channels)
channels = 1;
}
codec_def_t *def = codec_find(&name, MT_AUDIO);
if (!def) {
ilog(LOG_WARN, "No decoder for payload %s", payload_str);
return NULL;
}
if (def->supplemental || !def->support_decoding || def->media_type != MT_AUDIO) {
// not a real audio codec
ilog(LOG_DEBUG, "Not decoding codec %s", payload_str);
return NULL;
}
// decoder_new_fmt already handles the clockrate_mult scaling
int rtp_clockrate = clockrate;
clockrate = fraction_mult(clockrate, &def->default_clockrate_fact);
format_t out_format = {
.clockrate = clockrate,
.channels = channels,
.format = AV_SAMPLE_FMT_S16,
};
str fmtp = STR(format);
decoder_t *dec = decoder_new_fmtp(def, rtp_clockrate, channels, ptime, &out_format, NULL, &fmtp, NULL);
if (!dec)
return NULL;
decode_t *deco = g_new0(decode_t, 1);
deco->dec = dec;
return deco;
}
static int decoder_got_frame(decoder_t *dec, AVFrame *frame, void *sp, void *dp) {
ssrc_t *ssrc = sp;
metafile_t *metafile = ssrc->metafile;
output_t *output = ssrc->output;
stream_t *stream = ssrc->stream;
decode_t *deco = dp;
dbg("got frame pts %llu samples %u contents %02x%02x%02x%02x...", (unsigned long long) frame->pts, frame->nb_samples,
(unsigned int) frame->extended_data[0][0],
(unsigned int) frame->extended_data[0][1],
(unsigned int) frame->extended_data[0][2],
(unsigned int) frame->extended_data[0][3]);
if (metafile->recording_on) {
sink_add(&deco->mix_sink, frame);
if (output) {
dbg("SSRC %lx of stream #%lu has single output", ssrc->ssrc, stream->id);
if (!sink_add(&output->sink, frame))
ilog(LOG_ERR, "Failed to add decoded packet to individual output");
}
}
if (metafile->forwarding_on)
sink_add(&deco->tls_mix_sink, frame);
if (ssrc->tls_fwd) {
dbg("SSRC %lx of stream #%lu has TLS forwarding stream", ssrc->ssrc, stream->id);
if (!sink_add(&ssrc->tls_fwd->sink, frame))
ilog(LOG_ERR, "Failed to add decoded packet to TLS/TCP forward output");
}
av_frame_free(&frame);
return 0;
}
int decoder_input(decode_t *deco, const str *data, unsigned long ts, ssrc_t *ssrc) {
return decoder_input_data(deco->dec, data, ts, decoder_got_frame, ssrc, deco);
}
void decoder_free(decode_t *deco) {
if (!deco)
return;
decoder_close(deco->dec);
sink_close(&deco->mix_sink);
sink_close(&deco->tls_mix_sink);
g_free(deco);
}
|