Browse Source

MT#55283 explicitly return PTS/duration

... from packetizer function instead of putting it into the AVPacket.

Remove AVPacket from callback function arguments.

Fix up PTS/duration adjustments where they were missing.

Closes #1963

Change-Id: Ib36b36bb6648b0579dd83155c7217317dda29cc3
rfuchs/1971
Richard Fuchs 5 months ago
parent
commit
fa8123e1c2
6 changed files with 65 additions and 33 deletions
  1. +16
    -12
      daemon/codec.c
  2. +9
    -8
      daemon/media_player.c
  3. +3
    -2
      include/codec.h
  4. +33
    -9
      lib/codeclib.c
  5. +2
    -1
      lib/codeclib.h
  6. +2
    -1
      t/test-amr-encode.c

+ 16
- 12
daemon/codec.c View File

@ -285,8 +285,9 @@ static transcode_job_q transcode_jobs = TYPED_GQUEUE_INIT;
static tc_code (*__rtp_decode)(struct codec_ssrc_handler *ch, struct codec_ssrc_handler *input_ch,
struct transcode_packet *packet, struct media_packet *mp);
static void transcode_job_free(struct transcode_job *j);
static void packet_encoded_tx(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp,
str *inout, char *buf, unsigned int pkt_len, const struct fraction *cr_fact);
static void packet_encoded_tx(struct codec_ssrc_handler *ch, struct media_packet *mp,
str *inout, char *buf, unsigned int pkt_len, int64_t pts, int64_t duration,
const struct fraction *cr_fact);
static void codec_output_rtp_seq_passthrough(struct media_packet *mp, struct codec_scheduler *csch,
struct codec_handler *handler,
@ -4519,8 +4520,9 @@ static void __free_ssrc_handler(struct codec_ssrc_handler *ch) {
void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp,
packetizer_f pkt_f, void *pkt_f_data, const struct fraction *cr_fact,
void (*tx_f)(AVPacket *, struct codec_ssrc_handler *, struct media_packet *, str *,
char *, unsigned int, const struct fraction *cr_fact))
void (*tx_f)(struct codec_ssrc_handler *, struct media_packet *, str *,
char *, unsigned int, int64_t pts, int64_t duration,
const struct fraction *cr_fact))
{
// run this through our packetizer
AVPacket *in_pkt = pkt;
@ -4538,10 +4540,11 @@ void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, stru
// and request a packet
if (in_pkt)
ilogs(transcoding, LOG_DEBUG, "Adding %i bytes to packetizer", in_pkt->size);
int64_t pts, duration;
int ret = pkt_f(in_pkt,
ch->sample_buffer, &inout, pkt_f_data);
ch->sample_buffer, &inout, pkt_f_data, &pts, &duration);
if (G_UNLIKELY(ret == -1 || pkt->pts == AV_NOPTS_VALUE)) {
if (G_UNLIKELY(ret == -1 || pts == AV_NOPTS_VALUE)) {
// nothing
bufferpool_unref(buf);
break;
@ -4549,7 +4552,7 @@ void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, stru
ilogs(transcoding, LOG_DEBUG, "Received packet of %zu bytes from packetizer", inout.len);
tx_f(pkt, ch, mp, &inout, buf, pkt_len, cr_fact);
tx_f(ch, mp, &inout, buf, pkt_len, pts, duration, cr_fact);
if (ret == 0) {
// no more to go
@ -4598,8 +4601,9 @@ static void codec_output_rtp_seq_own(struct media_packet *mp, struct codec_sched
0, payload_type, ts_delay);
}
static void packet_encoded_tx(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp,
str *inout, char *buf, unsigned int pkt_len, const struct fraction *cr_fact)
static void packet_encoded_tx(struct codec_ssrc_handler *ch, struct media_packet *mp,
str *inout, char *buf, unsigned int pkt_len, int64_t pts, int64_t duration,
const struct fraction *cr_fact)
{
// check special payloads
@ -4612,7 +4616,7 @@ static void packet_encoded_tx(AVPacket *pkt, struct codec_ssrc_handler *ch, stru
int is_dtmf = 0;
if (dtmf_pt != -1)
is_dtmf = dtmf_event_payload(inout, (uint64_t *) &pkt->pts, pkt->duration,
is_dtmf = dtmf_event_payload(inout, (uint64_t *) &pts, duration,
&ch->dtmf_event, &ch->dtmf_events);
if (is_dtmf) {
payload_type = dtmf_pt;
@ -4628,7 +4632,7 @@ static void packet_encoded_tx(AVPacket *pkt, struct codec_ssrc_handler *ch, stru
ts_delay = ntohs(ev_pt->duration) - (ch->handler->dest_pt.ptime * ch->handler->dest_pt.clock_rate / 1000);
}
else {
if (is_silence_event(inout, &ch->silence_events, pkt->pts, pkt->duration))
if (is_silence_event(inout, &ch->silence_events, pts, duration))
payload_type = ch->handler->cn_payload_type;
}
@ -4642,7 +4646,7 @@ static void packet_encoded_tx(AVPacket *pkt, struct codec_ssrc_handler *ch, stru
memcpy(send_buf, buf, pkt_len);
}
ch->codec_output_rtp_seq(mp, &ch->csch, ch->handler, send_buf, inout->len, ch->csch.first_ts
+ fraction_divl(pkt->pts, cr_fact),
+ fraction_divl(pts, cr_fact),
ch->rtp_mark ? 1 : 0,
payload_type, ts_delay);
mp->ssrc_out->seq_diff++;


+ 9
- 8
daemon/media_player.c View File

@ -816,20 +816,21 @@ static void media_player_cache_entry_decoder_thread(void *p) {
obj_release(entry);
}
static void packet_encoded_cache(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp,
str *s, char *buf, unsigned int pkt_len, const struct fraction *cr_fact)
static void packet_encoded_cache(struct codec_ssrc_handler *ch, struct media_packet *mp,
str *s, char *buf, unsigned int pkt_len,
int64_t pts, int64_t dur, const struct fraction *cr_fact)
{
struct media_player_cache_entry *entry = mp->cache_entry;
struct media_player_cache_packet *ep = g_new0(__typeof(*ep), 1);
long duration = fraction_divl(pkt->duration, cr_fact);
long duration = fraction_divl(dur, cr_fact);
*ep = (__typeof__(*ep)) {
.buf = buf,
.s = *s,
.pts = pkt->pts,
.pts = pts,
.duration_ts = duration,
.duration = (long long) duration * 1000000LL
.duration = duration * 1000000LL
/ entry->coder.handler->dest_pt.clock_rate,
};
@ -838,9 +839,9 @@ static void packet_encoded_cache(AVPacket *pkt, struct codec_ssrc_handler *ch, s
if (entry->kernel_idx != -1) {
ilog(LOG_DEBUG, "Adding media packet (length %zu, TS %" PRIu64 ", delay %lu ms) to kernel packet stream %i",
s->len, pkt->pts, entry->duration, entry->kernel_idx);
if (!kernel_add_stream_packet(entry->kernel_idx, s->s, s->len, entry->duration, pkt->pts,
pkt->duration))
s->len, pts, entry->duration, entry->kernel_idx);
if (!kernel_add_stream_packet(entry->kernel_idx, s->s, s->len, entry->duration, pts,
dur))
ilog(LOG_ERR | LOG_FLAG_LIMIT, "Failed to add packet to kernel player (%s)", strerror(errno));
}


+ 3
- 2
include/codec.h View File

@ -254,8 +254,9 @@ void codec_handlers_stop(codec_handlers_q *, struct call_media *sink, bool clear
void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp,
packetizer_f pkt_f, void *pkt_f_data, const struct fraction *cr_fact,
void (*tx_f)(AVPacket *, struct codec_ssrc_handler *, struct media_packet *, str *,
char *, unsigned int, const struct fraction *cr_fact));
void (*tx_f)(struct codec_ssrc_handler *, struct media_packet *, str *,
char *, unsigned int, int64_t pts, int64_t duration,
const struct fraction *cr_fact));
void codec_output_rtp(struct media_packet *mp, struct codec_scheduler *,
struct codec_handler *handler, // normally == ch->handler except for DTMF
char *buf, // malloc'd, room for rtp_header + filled-in payload


+ 33
- 9
lib/codeclib.c View File

@ -2159,7 +2159,9 @@ int encoder_input_fifo(encoder_t *enc, AVFrame *frame,
}
int packetizer_passthrough(AVPacket *pkt, GString *buf, str *output, encoder_t *enc) {
int packetizer_passthrough(AVPacket *pkt, GString *buf, str *output, encoder_t *enc,
int64_t *__restrict pts, int64_t *__restrict duration)
{
if (!pkt)
return -1;
if (output->len < pkt->size) {
@ -2169,22 +2171,29 @@ int packetizer_passthrough(AVPacket *pkt, GString *buf, str *output, encoder_t *
}
output->len = pkt->size;
memcpy(output->s, pkt->data, pkt->size);
*pts = pkt->pts;
*duration = pkt->duration;
return 0;
}
// returns: -1 = not enough data, nothing returned; 0 = returned a packet;
// 1 = returned a packet and there's more
static int packetizer_samplestream(AVPacket *pkt, GString *buf, str *input_output, encoder_t *enc) {
static int packetizer_samplestream(AVPacket *pkt, GString *buf, str *input_output, encoder_t *enc,
int64_t *__restrict pts, int64_t *__restrict duration)
{
// avoid moving buffers around if possible:
// most common case: new input packet has just enough (or more) data as what we need
if (G_LIKELY(pkt && buf->len == 0 && pkt->size >= input_output->len)) {
*pts = pkt->pts;
*duration = pkt->duration;
memcpy(input_output->s, pkt->data, input_output->len);
// any leftovers?
if (pkt->size > input_output->len) {
g_string_append_len(buf, (char *) pkt->data + input_output->len,
pkt->size - input_output->len);
enc->packet_pts = pkt->pts + input_output->len
*duration = input_output->len
* (fraction_mult(enc->def->bits_per_sample, &enc->clockrate_fact) / 8);
enc->packet_pts = pkt->pts + *duration;
}
return buf->len >= input_output->len ? 1 : 0;
}
@ -2198,9 +2207,9 @@ static int packetizer_samplestream(AVPacket *pkt, GString *buf, str *input_outpu
memcpy(input_output->s, buf->str, input_output->len);
g_string_erase(buf, 0, input_output->len);
// adjust output pts
enc->avpkt->pts = enc->packet_pts;
enc->packet_pts += input_output->len
* fraction_mult(enc->def->bits_per_sample, &enc->clockrate_fact) / 8;
*pts = enc->packet_pts;
*duration = input_output->len * (fraction_mult(enc->def->bits_per_sample, &enc->clockrate_fact) / 8);
enc->packet_pts += *duration;
return buf->len >= input_output->len ? 1 : 0;
}
@ -3313,7 +3322,9 @@ static void amr_encoder_got_packet(encoder_t *enc) {
amr_encoder_mode_change(enc);
enc->avc.amr.pkt_seq++;
}
static int packetizer_amr(AVPacket *pkt, GString *buf, str *output, encoder_t *enc) {
static int packetizer_amr(AVPacket *pkt, GString *buf, str *output, encoder_t *enc,
int64_t *__restrict pts, int64_t *__restrict duration)
{
assert(pkt->size >= 1);
// CMR + TOC byte (already included) + optional ILL/ILP + optional CRC + payload
@ -3342,6 +3353,9 @@ static int packetizer_amr(AVPacket *pkt, GString *buf, str *output, encoder_t *e
unsigned char *s = (unsigned char *) output->s; // for safe bit shifting
*pts = pkt->pts;
*duration = enc->actual_format.clockrate * 20 / 1000; // 160 or 320
s[0] = '\xf0'; // no CMR req (4 bits)
// or do we have a CMR?
@ -3565,13 +3579,15 @@ static void bcg729_encoder_close(encoder_t *enc) {
enc->bcg729 = NULL;
}
static int packetizer_g729(AVPacket *pkt, GString *buf, str *input_output, encoder_t *enc) {
static int packetizer_g729(AVPacket *pkt, GString *buf, str *input_output, encoder_t *enc,
int64_t *__restrict pts, int64_t *__restrict duration)
{
// how many frames do we want?
int want_frames = input_output->len / 10;
// easiest case: we only want one frame. return what we got
if (want_frames == 1 && pkt)
return packetizer_passthrough(pkt, buf, input_output, enc);
return packetizer_passthrough(pkt, buf, input_output, enc, pts, duration);
// any other case, we go through our buffer
str output = *input_output; // remaining output buffer
@ -3588,12 +3604,15 @@ static int packetizer_g729(AVPacket *pkt, GString *buf, str *input_output, encod
&& have_noise_frames != 4)
return -1;
int64_t dur = 0;
// return non-silence/noise frames while we can
while (buf->len >= 10 && want_frames && output.len >= 10) {
memcpy(output.s, buf->str, 10);
g_string_erase(buf, 0, 10);
want_frames--;
str_shift(&output, 10);
dur += 80;
}
// append silence/noise frames if we can
@ -3602,8 +3621,13 @@ static int packetizer_g729(AVPacket *pkt, GString *buf, str *input_output, encod
g_string_erase(buf, 0, 2);
want_frames--;
str_shift(&output, 2);
dur += 80;
}
*pts = enc->packet_pts;
*duration = dur;
enc->packet_pts += dur;
if (output.len == input_output->len)
return -1; // got nothing
input_output->len = output.s - input_output->s;


+ 2
- 1
lib/codeclib.h View File

@ -103,7 +103,8 @@ typedef struct encoder_callback_s encoder_callback_t;
typedef struct dtx_method_s dtx_method_t;
typedef struct codec_cc_s codec_cc_t;
typedef int packetizer_f(AVPacket *, GString *, str *, encoder_t *);
typedef int packetizer_f(AVPacket *, GString *, str *, encoder_t *,
int64_t *__restrict pts, int64_t *__restrict dur);
typedef void format_init_f(struct rtp_payload_type *);
typedef void set_enc_options_f(encoder_t *, const str *);
typedef void set_dec_options_f(decoder_t *, const str *);


+ 2
- 1
t/test-amr-encode.c View File

@ -24,7 +24,8 @@ static int dec_cb(encoder_t *e, void *u1, void *u2) {
int plen = 256;
char payload[plen];
str inout = STR_LEN(payload, plen);
e->def->packetizer(e->avpkt, buf, &inout, e);
int64_t pts, dur;
e->def->packetizer(e->avpkt, buf, &inout, e, &pts, &dur);
if (inout.len != *expect_len
|| memcmp(inout.s, *expect, *expect_len))


Loading…
Cancel
Save