Skip to content

Commit 5e35862

Browse files
InterLinked1Friendly Automation
authored and
Friendly Automation
committed
translate.c: Prefer better codecs upon translate ties.
If multiple codecs are available for the same resource and the translation costs between multiple codecs are the same, ties are currently broken arbitrarily, which means a lower quality codec would be used. This forces Asterisk to explicitly use the higher quality codec, ceteris paribus. ASTERISK-29455 Change-Id: I4b7297e1baca7aac14fe4a3c7538e18e2dbe9fd6
1 parent 80e9e77 commit 5e35862

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed

doc/UPGRADE-staging/translate.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Subject: translate.c
2+
Master-Only: True
3+
4+
When setting up translation between two codecs the quality was not taken into account,
5+
resulting in suboptimal translation. The quality is now taken into account,
6+
which can reduce the number of translation steps required, and improve the resulting quality.

include/asterisk/codec.h

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct ast_codec {
7878
unsigned int smooth;
7979
/*! \brief Flags to be passed to the smoother */
8080
unsigned int smoother_flags;
81+
/*! \brief Format quality, on scale from 0 to 150 (100 is ulaw, the reference). This allows better format to be used, ceterus paribus. */
82+
unsigned int quality;
8183
/*! \brief The module that registered this codec */
8284
struct ast_module *mod;
8385
};

main/codec.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
142142
"\tIt does not indicate anything about your configuration.\n");
143143
}
144144

145-
ast_cli(a->fd, "%8s %-5s %-12s %-16s %s\n","ID","TYPE","NAME","FORMAT","DESCRIPTION");
145+
ast_cli(a->fd, "%8s %-5s %-12s %-16s %7s %s\n","ID","TYPE","NAME","FORMAT","QUALITY", "DESCRIPTION");
146146
ast_cli(a->fd, "------------------------------------------------------------------------------------------------\n");
147147

148148
ao2_rdlock(codecs);
@@ -171,11 +171,12 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
171171
}
172172
}
173173

174-
ast_cli(a->fd, "%8u %-5s %-12s %-16s (%s)\n",
174+
ast_cli(a->fd, "%8u %-5s %-12s %-16s %7d (%s)\n",
175175
codec->external.id,
176176
ast_codec_media_type2str(codec->external.type),
177177
codec->external.name,
178178
S_OR(codec->format_name, "no cached format"),
179+
codec->external.quality,
179180
codec->external.description);
180181
}
181182

main/codec_builtin.c

+28-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ static struct ast_codec g723 = {
105105
.minimum_bytes = 20,
106106
.samples_count = g723_samples,
107107
.get_length = g723_length,
108+
.quality = 20,
108109
};
109110

110111
static int codec2_samples(struct ast_frame *frame)
@@ -175,6 +176,7 @@ static struct ast_codec ulaw = {
175176
.samples_count = ulaw_samples,
176177
.get_length = ulaw_length,
177178
.smooth = 1,
179+
.quality = 100, /* We are the gold standard. */
178180
};
179181

180182
static struct ast_codec alaw = {
@@ -189,6 +191,7 @@ static struct ast_codec alaw = {
189191
.samples_count = ulaw_samples,
190192
.get_length = ulaw_length,
191193
.smooth = 1,
194+
.quality = 100, /* Just as good as ulaw */
192195
};
193196

194197
static int gsm_samples(struct ast_frame *frame)
@@ -213,6 +216,7 @@ static struct ast_codec gsm = {
213216
.samples_count = gsm_samples,
214217
.get_length = gsm_length,
215218
.smooth = 1,
219+
.quality = 60,
216220
};
217221

218222
static int g726_samples(struct ast_frame *frame)
@@ -237,6 +241,7 @@ static struct ast_codec g726rfc3551 = {
237241
.samples_count = g726_samples,
238242
.get_length = g726_length,
239243
.smooth = 1,
244+
.quality = 85,
240245
};
241246

242247
static struct ast_codec g726aal2 = {
@@ -251,6 +256,7 @@ static struct ast_codec g726aal2 = {
251256
.samples_count = g726_samples,
252257
.get_length = g726_length,
253258
.smooth = 1,
259+
.quality = 85,
254260
};
255261

256262
static struct ast_codec adpcm = {
@@ -265,6 +271,7 @@ static struct ast_codec adpcm = {
265271
.samples_count = g726_samples,
266272
.get_length = g726_length,
267273
.smooth = 1,
274+
.quality = 80,
268275
};
269276

270277
static int slin_samples(struct ast_frame *frame)
@@ -290,6 +297,7 @@ static struct ast_codec slin8 = {
290297
.get_length = slin_length,
291298
.smooth = 1,
292299
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
300+
.quality = 115, /* Better than ulaw */
293301
};
294302

295303
static struct ast_codec slin12 = {
@@ -305,6 +313,7 @@ static struct ast_codec slin12 = {
305313
.get_length = slin_length,
306314
.smooth = 1,
307315
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
316+
.quality = 116,
308317
};
309318

310319
static struct ast_codec slin16 = {
@@ -320,6 +329,7 @@ static struct ast_codec slin16 = {
320329
.get_length = slin_length,
321330
.smooth = 1,
322331
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
332+
.quality = 117,
323333
};
324334

325335
static struct ast_codec slin24 = {
@@ -335,6 +345,7 @@ static struct ast_codec slin24 = {
335345
.get_length = slin_length,
336346
.smooth = 1,
337347
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
348+
.quality = 118,
338349
};
339350

340351
static struct ast_codec slin32 = {
@@ -350,6 +361,7 @@ static struct ast_codec slin32 = {
350361
.get_length = slin_length,
351362
.smooth = 1,
352363
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
364+
.quality = 119,
353365
};
354366

355367
static struct ast_codec slin44 = {
@@ -365,6 +377,7 @@ static struct ast_codec slin44 = {
365377
.get_length = slin_length,
366378
.smooth = 1,
367379
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
380+
.quality = 120,
368381
};
369382

370383
static struct ast_codec slin48 = {
@@ -380,6 +393,7 @@ static struct ast_codec slin48 = {
380393
.get_length = slin_length,
381394
.smooth = 1,
382395
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
396+
.quality = 121,
383397
};
384398

385399
static struct ast_codec slin96 = {
@@ -395,6 +409,7 @@ static struct ast_codec slin96 = {
395409
.get_length = slin_length,
396410
.smooth = 1,
397411
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
412+
.quality = 122,
398413
};
399414

400415
static struct ast_codec slin192 = {
@@ -410,6 +425,7 @@ static struct ast_codec slin192 = {
410425
.get_length = slin_length,
411426
.smooth = 1,
412427
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
428+
.quality = 123,
413429
};
414430

415431
static int lpc10_samples(struct ast_frame *frame)
@@ -433,6 +449,7 @@ static struct ast_codec lpc10 = {
433449
.minimum_bytes = 7,
434450
.samples_count = lpc10_samples,
435451
.smooth = 1,
452+
.quality = 25,
436453
};
437454

438455
static int g729_samples(struct ast_frame *frame)
@@ -458,6 +475,7 @@ static struct ast_codec g729a = {
458475
.get_length = g729_length,
459476
.smooth = 1,
460477
.smoother_flags = AST_SMOOTHER_FLAG_G729,
478+
.quality = 20,
461479
};
462480

463481
static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
@@ -584,6 +602,7 @@ static struct ast_codec speex8 = {
584602
.default_ms = 20,
585603
.minimum_bytes = 10,
586604
.samples_count = speex8_samples,
605+
.quality = 40,
587606
};
588607

589608
static int speex16_samples(struct ast_frame *frame)
@@ -601,6 +620,7 @@ static struct ast_codec speex16 = {
601620
.default_ms = 20,
602621
.minimum_bytes = 10,
603622
.samples_count = speex16_samples,
623+
.quality = 40,
604624
};
605625

606626
static int speex32_samples(struct ast_frame *frame)
@@ -618,6 +638,7 @@ static struct ast_codec speex32 = {
618638
.default_ms = 20,
619639
.minimum_bytes = 10,
620640
.samples_count = speex32_samples,
641+
.quality = 40,
621642
};
622643

623644
static int ilbc_samples(struct ast_frame *frame)
@@ -641,6 +662,7 @@ static struct ast_codec ilbc = {
641662
.minimum_bytes = 38,
642663
.samples_count = ilbc_samples,
643664
.smooth = 0,
665+
.quality = 45,
644666
};
645667

646668
static struct ast_codec g722 = {
@@ -655,6 +677,7 @@ static struct ast_codec g722 = {
655677
.samples_count = g726_samples,
656678
.get_length = g726_length,
657679
.smooth = 1,
680+
.quality = 110, /* In theory, better than ulaw */
658681
};
659682

660683
static int siren7_samples(struct ast_frame *frame)
@@ -678,6 +701,7 @@ static struct ast_codec siren7 = {
678701
.minimum_bytes = 80,
679702
.samples_count = siren7_samples,
680703
.get_length = siren7_length,
704+
.quality = 85,
681705
};
682706

683707
static int siren14_samples(struct ast_frame *frame)
@@ -701,6 +725,7 @@ static struct ast_codec siren14 = {
701725
.minimum_bytes = 120,
702726
.samples_count = siren14_samples,
703727
.get_length = siren14_length,
728+
.quality = 90,
704729
};
705730

706731
static int g719_samples(struct ast_frame *frame)
@@ -724,6 +749,7 @@ static struct ast_codec g719 = {
724749
.minimum_bytes = 160,
725750
.samples_count = g719_samples,
726751
.get_length = g719_length,
752+
.quality = 95,
727753
};
728754

729755
static int opus_samples(struct ast_frame *frame)
@@ -751,6 +777,7 @@ static struct ast_codec opus = {
751777
.default_ms = 20,
752778
.samples_count = opus_samples,
753779
.minimum_bytes = 10,
780+
.quality = 50,
754781
};
755782

756783
static struct ast_codec jpeg = {
@@ -859,7 +886,7 @@ static struct ast_codec silk8 = {
859886
.maximum_ms = 100,
860887
.default_ms = 20,
861888
.minimum_bytes = 160,
862-
.samples_count = silk_samples
889+
.samples_count = silk_samples,
863890
};
864891

865892
static struct ast_codec silk12 = {

main/translate.c

+28
Original file line numberDiff line numberDiff line change
@@ -1465,11 +1465,39 @@ int ast_translator_best_choice(struct ast_format_cap *dst_cap,
14651465
beststeps = matrix_get(x, y)->multistep;
14661466
} else if (matrix_get(x, y)->table_cost == besttablecost
14671467
&& matrix_get(x, y)->multistep == beststeps) {
1468+
int replace = 0;
14681469
unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst);
14691470
unsigned int gap_current = format_sample_rate_absdiff(src, dst);
14701471

14711472
if (gap_current < gap_selected) {
14721473
/* better than what we have so far */
1474+
replace = 1;
1475+
} else if (gap_current == gap_selected) {
1476+
int src_quality, best_quality;
1477+
struct ast_codec *src_codec, *best_codec;
1478+
1479+
src_codec = ast_format_get_codec(src);
1480+
best_codec = ast_format_get_codec(best);
1481+
src_quality = src_codec->quality;
1482+
best_quality = best_codec->quality;
1483+
1484+
ao2_cleanup(src_codec);
1485+
ao2_cleanup(best_codec);
1486+
1487+
/* We have a tie, so choose the format with the higher quality, if they differ. */
1488+
if (src_quality > best_quality) {
1489+
/* Better than what we had before. */
1490+
replace = 1;
1491+
ast_debug(2, "Tiebreaker: preferring format %s (%d) to %s (%d)\n", ast_format_get_name(src), src_quality,
1492+
ast_format_get_name(best), best_quality);
1493+
} else {
1494+
/* This isn't necessarily indicative of a problem, but in reality this shouldn't really happen, unless
1495+
* there are 2 formats that are basically the same. */
1496+
ast_debug(1, "Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1497+
ast_format_get_name(src), ast_format_get_name(best), best_quality, ast_format_get_name(best));
1498+
}
1499+
}
1500+
if (replace) {
14731501
ao2_replace(best, src);
14741502
ao2_replace(bestdst, dst);
14751503
besttablecost = matrix_get(x, y)->table_cost;

0 commit comments

Comments
 (0)