Skip to content

Commit

Permalink
apply extended codec support
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcello Ceschia committed Apr 17, 2013
1 parent 91dea9a commit 7a8ce40
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 22 deletions.
2 changes: 2 additions & 0 deletions include/asterisk/astobj2.h
Expand Up @@ -17,6 +17,8 @@
#ifndef _ASTERISK_ASTOBJ2_H
#define _ASTERISK_ASTOBJ2_H

#define REF_DEBUG 1

#include "asterisk/compat.h"
#include "asterisk/lock.h"

Expand Down
11 changes: 11 additions & 0 deletions include/asterisk/format.h
Expand Up @@ -219,6 +219,10 @@ struct ast_format_attr_interface {
* \retval -1 failure, Value was either not found, or not allowed to be accessed.
*/
int (* const format_attr_get_val)(const struct ast_format_attr *format_attr, int key, void *val);

int (* const format_samples)(const struct ast_frame *f);
int (* const format_rate)(const struct ast_frame *f);
int (* const allowSmoother)(void);

/*
* \brief Parse SDP attribute information, interpret it, and store it in ast_format_attr structure.
Expand Down Expand Up @@ -471,4 +475,11 @@ int ast_format_is_slinear(const struct ast_format *format);
* \brief Get the best slinear format id for a given sample rate
*/
enum ast_format_id ast_format_slin_by_rate(unsigned int rate);

int ast_format_custom_add(struct ast_format_list *newFormat);
int ast_format_custom_get_samples(const struct ast_format *format, const struct ast_frame *f);
int ast_format_custom_get_rate(const struct ast_format *format);
int ast_format_custom_requestFormatId(enum ast_format_type);
int ast_format_custom_register(struct ast_format_attr_interface *newFormat, enum ast_format_type formatType);
int ast_format_allowSmoother(const struct ast_format *format);
#endif /* _AST_FORMAT_H */
3 changes: 3 additions & 0 deletions include/asterisk/rtp_engine.h
Expand Up @@ -2108,6 +2108,9 @@ void ast_rtp_dtls_cfg_copy(const struct ast_rtp_dtls_cfg *src_cfg, struct ast_rt
*/
void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg);

void ast_add_mime_type(const struct ast_format *format, int rtp_code, char *type, char *subtype, unsigned int sample_rate);
void ast_add_static_payload(int map, const struct ast_format *format, int rtp_code);

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions main/channel.c
Expand Up @@ -925,6 +925,8 @@ struct ast_format *ast_best_codec(struct ast_format_cap *cap, struct ast_format
AST_FORMAT_G729A,
/*! Down to G.723.1 which is proprietary but at least designed for voice */
AST_FORMAT_G723_1,

//TODO how to handle custom formats
};
char buf[512];
int x;
Expand Down
94 changes: 92 additions & 2 deletions main/format.c
Expand Up @@ -172,7 +172,7 @@ static int format_set_helper(struct ast_format *format, va_list ap)
struct interface_ao2_wrapper *wrapper;

if (!(wrapper = find_interface(format))) {
ast_log(LOG_WARNING, "Could not find format interface to set.\n");
ast_log(LOG_WARNING, "Could not find format interface for %d to set.\n", format->id);
return -1;
}

Expand Down Expand Up @@ -729,6 +729,8 @@ const char *ast_codec2str(struct ast_format *format)

int ast_format_rate(const struct ast_format *format)
{
int rate;

switch (format->id) {
case AST_FORMAT_SLINEAR12:
return 12000;
Expand Down Expand Up @@ -783,7 +785,8 @@ int ast_format_rate(const struct ast_format *format)
}
}
default:
return 8000;
rate = 16000;//ast_format_custom_get_rate(format);
return (rate > 0) ? rate : 8000;
}
}

Expand Down Expand Up @@ -1431,3 +1434,90 @@ int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *inte
f_list = ast_format_list_destroy(f_list);
return 0;
}


int ast_format_custom_add(struct ast_format_list *newFormat){
int res = 0;

ast_log(LOG_NOTICE, "Add new Format %s\n", newFormat->name);
res = format_list_add_custom(newFormat);
build_format_list_array();
return res;
}

int ast_format_custom_get_samples(const struct ast_format *format, const struct ast_frame *f){
struct interface_ao2_wrapper *wrapper;
int samples = 0;

if ((wrapper = find_interface(format))) {
if (wrapper->interface && wrapper->interface->format_samples) {
samples = wrapper->interface->format_samples(f);
}
ao2_ref(wrapper, -1);
}

return samples;
}

int ast_format_custom_get_rate(const struct ast_format *format){
struct interface_ao2_wrapper *wrapper;
int rate = -1;

if ((wrapper = find_interface(format))) {
if (wrapper->interface && wrapper->interface->format_rate) {
rate = wrapper->interface->format_rate(&format->fattr);
}
ao2_ref(wrapper, -1);
}

return rate;
}
int ast_format_allowSmoother(const struct ast_format *format){
struct interface_ao2_wrapper *wrapper;
int result = 1;

if ((wrapper = find_interface(format))) {
if (wrapper->interface && wrapper->interface->allowSmoother) {
result = wrapper->interface->allowSmoother();
}
ao2_ref(wrapper, -1);
}

return result;
}


int ast_format_custom_register(struct ast_format_attr_interface *newFormatInterface, enum ast_format_type formatType){

int x = 1;
int i;
size_t f_len;
const struct ast_format_list *f_list;

ao2_wrlock(interfaces);

/* if this format does not have a format id, get some new */
ast_log(LOG_NOTICE, "register new codec with id: %d\n", newFormatInterface->id);
// if(newFormatInterface->id < 1){

ast_log(LOG_NOTICE, "search for new id\n");

f_list = ast_format_list_get(&f_len);
for (x = 0; x < f_len; x++) {
if (AST_FORMAT_GET_TYPE(f_list[x].format.id) == formatType) {
i = f_list[x].format.id;
}
}
f_list = ast_format_list_destroy(f_list);


newFormatInterface->id = ++i;
ast_log(LOG_NOTICE, "found new id %d\n", newFormatInterface->id);

// }
ao2_unlock(interfaces);

ast_format_attr_reg_interface(newFormatInterface);

return 0;
}
5 changes: 4 additions & 1 deletion main/frame.c
Expand Up @@ -1084,7 +1084,10 @@ int ast_codec_get_samples(struct ast_frame *f)
samples = ast_format_rate(&f->subclass.format) / 50;
break;
default:
ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format));
samples = ast_format_custom_get_samples(&f->subclass.format, f);
if(!samples){
ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format));
}
}
return samples;
}
Expand Down
10 changes: 9 additions & 1 deletion main/rtp_engine.c
Expand Up @@ -594,6 +594,7 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
* rates are not compared */
if (sample_rate && t->sample_rate &&
(sample_rate != t->sample_rate)) {
ast_log(LOG_WARNING, "sample rate does not match for %s\n", mimesubtype);
continue;
}

Expand Down Expand Up @@ -623,7 +624,7 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
break;
}
ast_rwlock_unlock(&mime_types_lock);

ast_log(LOG_WARNING, "found: %d\n", found);
return (found ? 0 : -2);
}

Expand Down Expand Up @@ -2333,3 +2334,10 @@ int ast_rtp_engine_init()

return 0;
}

void ast_add_mime_type(const struct ast_format *format, int rtp_code, char *type, char *subtype, unsigned int sample_rate){
return set_next_mime_type(format, rtp_code, type, subtype, sample_rate);
}
void ast_add_static_payload(int map, const struct ast_format *format, int rtp_code){
return add_static_payload(map, format, rtp_code);
}
4 changes: 4 additions & 0 deletions res/res_format_attr_h264.c
Expand Up @@ -270,6 +270,10 @@ static void h264_format_attr_sdp_generate(const struct ast_format_attr *format_a
if (!added) {
ast_str_append(str, 0, "a=fmtp:%d profile-level-id=%X%X%X", payload, format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);



ast_str_append(str, 0, "\r\na=orient:portrait\r\na=rtcp-fb:* nack pli");
added = 1;
} else {
ast_str_append(str, 0, ";profile-level-id=%X%X%X", format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
Expand Down
44 changes: 26 additions & 18 deletions res/res_rtp_asterisk.c
Expand Up @@ -2607,6 +2607,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
struct ast_sockaddr remote_address = { {0,} };
struct ast_format subclass;
int codec;
int allowSmoother = 1;

ast_rtp_instance_get_remote_address(instance, &remote_address);

Expand Down Expand Up @@ -2652,12 +2653,11 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
rtp->smoother = NULL;
}
}

/* If no smoother is present see if we have to set one up */
if (!rtp->smoother) {
struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass);

switch (subclass.id) {

allowSmoother = ast_format_allowSmoother(&subclass);

/* disable smoother for frame based formats */
switch (subclass.id) {
case AST_FORMAT_SPEEX:
case AST_FORMAT_SPEEX16:
case AST_FORMAT_SPEEX32:
Expand All @@ -2667,21 +2667,29 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
case AST_FORMAT_SIREN7:
case AST_FORMAT_SIREN14:
case AST_FORMAT_G719:
/* these are all frame-based codecs and cannot be safely run through
a smoother */
break;

allowSmoother = 0;
break;
default:
if (fmt.inc_ms) {
if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
return -1;
}
if (fmt.flags) {
ast_smoother_set_flags(rtp->smoother, fmt.flags);
}
ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
break;
}


/* If no smoother is present see if we have to set one up */
if (!rtp->smoother && allowSmoother) {
struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass);

if (fmt.inc_ms) {
if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
return -1;
}
if (fmt.flags) {
ast_smoother_set_flags(rtp->smoother, fmt.flags);
}
ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
}

}

/* Feed audio frames into the actual function that will create a frame and send it */
Expand Down

0 comments on commit 7a8ce40

Please sign in to comment.