diff options
-rw-r--r-- | addons/chan_ooh323.c | 19 | ||||
-rw-r--r-- | addons/ooh323c/src/context.c | 1 | ||||
-rw-r--r-- | addons/ooh323c/src/memheap.c | 11 | ||||
-rw-r--r-- | addons/ooh323c/src/ooCalls.c | 3 | ||||
-rw-r--r-- | addons/ooh323c/src/ooCapability.c | 8 | ||||
-rw-r--r-- | addons/ooh323c/src/ooGkClient.c | 3 | ||||
-rw-r--r-- | addons/ooh323c/src/ooh245.c | 2 | ||||
-rw-r--r-- | addons/ooh323c/src/ooq931.c | 6 | ||||
-rw-r--r-- | bridges/bridge_softmix.c | 34 | ||||
-rw-r--r-- | formats/format_pcm.c | 41 | ||||
-rw-r--r-- | include/asterisk/stream.h | 78 | ||||
-rw-r--r-- | main/Makefile | 3 | ||||
-rw-r--r-- | main/cli.c | 12 | ||||
-rw-r--r-- | main/sdp.c | 3 | ||||
-rw-r--r-- | main/sdp_state.c | 4 | ||||
-rw-r--r-- | main/stream.c | 135 | ||||
-rw-r--r-- | menuselect/Makefile | 8 | ||||
-rw-r--r-- | menuselect/autoconfig.h.in | 4 | ||||
-rwxr-xr-x | menuselect/configure | 33 | ||||
-rw-r--r-- | menuselect/configure.ac | 40 | ||||
-rw-r--r-- | res/Makefile | 3 | ||||
-rw-r--r-- | tests/test_stream.c | 120 |
22 files changed, 390 insertions, 181 deletions
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index ffdbf6721..b456796d7 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -1281,7 +1281,7 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast); char *callToken = (char *)NULL; - int res = -1; + int res = -1, rres; if (!p) return -1; @@ -1328,11 +1328,9 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d case AST_CONTROL_PROGRESS: if (ast_channel_state(ast) != AST_STATE_UP) { if (!p->progsent) { + rres = ooManualProgress(callToken); if (gH323Debug) { - ast_debug(1, "Sending manual progress for %s, res = %u\n", callToken, - ooManualProgress(callToken)); - } else { - ooManualProgress(callToken); + ast_debug(1, "Sending manual progress for %s, res = %u\n", callToken, rres); } p->progsent = 1; } @@ -1341,12 +1339,9 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d case AST_CONTROL_RINGING: if (ast_channel_state(ast) == AST_STATE_RING || ast_channel_state(ast) == AST_STATE_RINGING) { if (!p->alertsent) { + rres = ooManualRingback(callToken); if (gH323Debug) { - ast_debug(1, "Sending manual ringback for %s, res = %u\n", - callToken, - ooManualRingback(callToken)); - } else { - ooManualRingback(callToken); + ast_debug(1, "Sending manual ringback for %s, res = %u\n", callToken, rres); } p->alertsent = 1; } @@ -5053,9 +5048,7 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p) ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(p->owner),target_context); } p->faxdetected = 1; - if (dfr) { - ast_frfree(dfr); - } + ast_frfree(dfr); return &ast_null_frame; } } diff --git a/addons/ooh323c/src/context.c b/addons/ooh323c/src/context.c index bc3db4387..c1e2003a2 100644 --- a/addons/ooh323c/src/context.c +++ b/addons/ooh323c/src/context.c @@ -164,6 +164,7 @@ OOCTXT* newContext () /* ASN1CRTFREE0 (pctxt); */ ast_free(pctxt); pctxt = 0; + return (pctxt); } pctxt->flags |= ASN1DYNCTXT; } diff --git a/addons/ooh323c/src/memheap.c b/addons/ooh323c/src/memheap.c index 4bcbd7a3d..4020261bb 100644 --- a/addons/ooh323c/src/memheap.c +++ b/addons/ooh323c/src/memheap.c @@ -623,7 +623,7 @@ void memHeapFreePtr (void** ppvMemHeap, void* mem_p) } } } - if (!ISLAST (pElem) && ISFREE (GETNEXT (pElem))) { + if (pElem && !ISLAST (pElem) && ISFREE (GETNEXT (pElem))) { OSMemElemDescr* nextelem_p = GETNEXT (pElem); /* +1 because the OSMemElemDescr has size ONE unit (8 bytes) */ @@ -638,7 +638,7 @@ void memHeapFreePtr (void** ppvMemHeap, void* mem_p) } /* correct the prevOff field of next element */ - if (!ISLAST (pElem)) { + if (pElem && !ISLAST (pElem)) { OSMemElemDescr* nextelem_p = GETNEXT (pElem); pElem_prevOff (nextelem_p) = QOFFSETOF (nextelem_p, pElem); } @@ -686,7 +686,7 @@ static void initNewFreeElement (OSMemBlk* pMemBlk, } pNextElem = GETNEXT (pNewElem); - if (ISFREE (pNextElem)) { + if (pNextElem && ISFREE (pNextElem)) { /* if the next elem is free, then unite them together */ @@ -820,7 +820,7 @@ void* memHeapRealloc (void** ppvMemHeap, void* mem_p, int nbytes_) /* look for free element after pElem */ pNextElem = GETNEXT (pElem); - if (ISFREE (pNextElem)) { + if (pNextElem && ISFREE (pNextElem)) { /* +1 'cos sizeof (OSMemElemDescr) == 1 unit */ sumSize += pElem_nunits (pNextElem) + 1; freeMem++; @@ -1062,7 +1062,7 @@ void memHeapAddRef (void** ppvMemHeap) void memHeapRelease (void** ppvMemHeap) { OSMemHeap** ppMemHeap = (OSMemHeap**)ppvMemHeap; - OSMemHeap* pMemHeap = *ppMemHeap; + OSMemHeap* pMemHeap; if (ppMemHeap != 0 && *ppMemHeap != 0 && --(*ppMemHeap)->refCnt == 0) { OSMemLink* pMemLink, *pMemLink2; @@ -1080,6 +1080,7 @@ void memHeapRelease (void** ppvMemHeap) } if ((*ppMemHeap)->flags & RT_MH_FREEHEAPDESC) { + pMemHeap = *ppMemHeap; ast_mutex_destroy(&pMemHeap->pLock); ast_free(*ppMemHeap); } diff --git a/addons/ooh323c/src/ooCalls.c b/addons/ooh323c/src/ooCalls.c index 3097c6d28..15ab3258f 100644 --- a/addons/ooh323c/src/ooCalls.c +++ b/addons/ooh323c/src/ooCalls.c @@ -805,8 +805,7 @@ int ooAddMediaInfo(OOH323CallData *call, OOMediaInfo mediaInfo) if(!call) { - OOTRACEERR3("Error:Invalid 'call' param for ooAddMediaInfo.(%s, %s)\n", - call->callType, call->callToken); + OOTRACEERR1("Error:Invalid 'call' param for ooAddMediaInfo.\n"); return OO_FAILED; } newMediaInfo = (OOMediaInfo*) memAlloc(call->pctxt, sizeof(OOMediaInfo)); diff --git a/addons/ooh323c/src/ooCapability.c b/addons/ooh323c/src/ooCapability.c index 731478346..0796c46bf 100644 --- a/addons/ooh323c/src/ooCapability.c +++ b/addons/ooh323c/src/ooCapability.c @@ -62,8 +62,6 @@ int ooCapabilityEnableDTMFCISCO /*Dynamic RTP payload type range is from 96 - 127 */ if(dynamicRTPPayloadType >= 96 && dynamicRTPPayloadType <= 127) gcDynamicRTPPayloadType = dynamicRTPPayloadType; - else - call->dtmfcodec = dynamicRTPPayloadType; } else{ call->dtmfmode |= OO_CAP_DTMF_CISCO; @@ -623,8 +621,7 @@ int ooCapabilityAddT38Capability else pctxt = call->pctxt; epCap = (ooH323EpCapability*)memAllocZ(pctxt, sizeof(ooH323EpCapability)); - params = (OOCapParams*) memAlloc(pctxt, sizeof(OOCapParams)); - memset(params, 0 , sizeof(OOCapParams)); + params = (OOCapParams*) memAllocZ(pctxt, sizeof(OOCapParams)); if(!epCap || !params) { OOTRACEERR1("ERROR: Memory - ooCapabilityAddT38Capability - " @@ -808,8 +805,7 @@ void* ooCapabilityCreateDTMFCapability(int cap, int dtmfcodec, OOCTXT *pctxt) } memset(pATECap, 0, sizeof(H245AudioTelephonyEventCapability)); pATECap->dynamicRTPPayloadType = dtmfcodec; - events = (char*)memAlloc(pctxt, strlen("0-16")+1); - memset(events, 0, strlen("0-16")+1); + events = (char*)memAllocZ(pctxt, strlen("0-16")+1); if(!events) { OOTRACEERR1("Error:Memory - ooCapabilityCreateDTMFCapability - events\n"); diff --git a/addons/ooh323c/src/ooGkClient.c b/addons/ooh323c/src/ooGkClient.c index a307f4eef..0168ee7de 100644 --- a/addons/ooh323c/src/ooGkClient.c +++ b/addons/ooh323c/src/ooGkClient.c @@ -2332,9 +2332,8 @@ int ooGkClientSendIRR pIRR->m.perCallInfoPresent = TRUE; perCallInfo = - (H225InfoRequestResponse_perCallInfo_element *)memAlloc(pctxt, + (H225InfoRequestResponse_perCallInfo_element *)memAllocZ(pctxt, sizeof(H225InfoRequestResponse_perCallInfo_element)); - memset(perCallInfo, 0, sizeof(H225InfoRequestResponse_perCallInfo_element)); if(!perCallInfo) { diff --git a/addons/ooh323c/src/ooh245.c b/addons/ooh323c/src/ooh245.c index adff91790..fe8ff28e0 100644 --- a/addons/ooh323c/src/ooh245.c +++ b/addons/ooh323c/src/ooh245.c @@ -356,7 +356,6 @@ int ooSendTermCapMsg(OOH323CallData *call) /* pctxt = &gH323ep.msgctxt; */ pctxt = call->msgctxt; ph245msg->msgType = OOTerminalCapabilitySet; - memset(request, 0, sizeof(H245RequestMessage)); if(request == NULL) { OOTRACEERR3("ERROR: No memory allocated for request message (%s, %s)\n", @@ -364,6 +363,7 @@ int ooSendTermCapMsg(OOH323CallData *call) return OO_FAILED; } + memset(request, 0, sizeof(H245RequestMessage)); request->t = T_H245RequestMessage_terminalCapabilitySet; request->u.terminalCapabilitySet = (H245TerminalCapabilitySet*) memAlloc(pctxt, sizeof(H245TerminalCapabilitySet)); diff --git a/addons/ooh323c/src/ooq931.c b/addons/ooh323c/src/ooq931.c index 1ca361c2c..01a8e4aaf 100644 --- a/addons/ooh323c/src/ooq931.c +++ b/addons/ooh323c/src/ooq931.c @@ -2439,8 +2439,10 @@ int ooH323HandleCallFwdRequest(OOH323CallData *call) alias = call->pCallFwdData->aliases; while(alias) { - pNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases)); - pNewAlias->value = (char*) memAlloc(pctxt, strlen(alias->value)+1); + pNewAlias = (ooAliases*) memAllocZ(pctxt, sizeof(ooAliases)); + if (pNewAlias) { + pNewAlias->value = (char*) memAllocZ(pctxt, strlen(alias->value)+1); + } if(!pNewAlias || !pNewAlias->value) { OOTRACEERR3("Error:Memory - ooH323HandleCallFwdRequest - " diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index f0a3fb42d..ed88b7cd5 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -1318,6 +1318,12 @@ static void remb_collect_report(struct ast_bridge *bridge, struct ast_bridge_cha break; } } + + /* After the report is integrated we reset this to 0 in case they stop producing + * REMB reports. + */ + sc->remb.br_mantissa = 0; + sc->remb.br_exp = 0; } static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct softmix_channel *sc) @@ -1328,20 +1334,18 @@ static void remb_send_report(struct ast_bridge_channel *bridge_channel, struct s return; } - /* If we have a new bitrate then use it for the REMB, if not we use the previous - * one until we know otherwise. This way the bitrate doesn't drop to 0 all of a sudden. + /* We always do this calculation as even when the bitrate is zero the browser + * still prefers it to be accurate instead of lying. */ - if (sc->remb_collector->bitrate) { - sc->remb_collector->feedback.remb.br_mantissa = sc->remb_collector->bitrate; - sc->remb_collector->feedback.remb.br_exp = 0; + sc->remb_collector->feedback.remb.br_mantissa = sc->remb_collector->bitrate; + sc->remb_collector->feedback.remb.br_exp = 0; - /* The mantissa only has 18 bits available, so while it exceeds them we bump - * up the exp. - */ - while (sc->remb_collector->feedback.remb.br_mantissa > 0x3ffff) { - sc->remb_collector->feedback.remb.br_mantissa = sc->remb_collector->feedback.remb.br_mantissa >> 1; - sc->remb_collector->feedback.remb.br_exp++; - } + /* The mantissa only has 18 bits available, so while it exceeds them we bump + * up the exp. + */ + while (sc->remb_collector->feedback.remb.br_mantissa > 0x3ffff) { + sc->remb_collector->feedback.remb.br_mantissa = sc->remb_collector->feedback.remb.br_mantissa >> 1; + sc->remb_collector->feedback.remb.br_exp++; } for (i = 0; i < AST_VECTOR_SIZE(&bridge_channel->stream_map.to_bridge); ++i) { @@ -2062,6 +2066,7 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st struct ast_bridge_channel *participant; struct ast_vector_int media_types; int nths[AST_MEDIA_TYPE_END] = {0}; + int idx; switch (bridge->softmix.video_mode.mode) { case AST_BRIDGE_VIDEO_MODE_NONE: @@ -2080,7 +2085,10 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st * When channels end up getting added back in they'll reuse their existing * collector and won't need to allocate a new one (unless they were just added). */ - AST_VECTOR_RESET(&softmix_data->remb_collectors, ao2_cleanup); + for (idx = 0; idx < AST_VECTOR_SIZE(&softmix_data->remb_collectors); ++idx) { + ao2_cleanup(AST_VECTOR_GET(&softmix_data->remb_collectors, idx)); + AST_VECTOR_REPLACE(&softmix_data->remb_collectors, idx, NULL); + } /* First traversal: re-initialize all of the participants' stream maps */ AST_LIST_TRAVERSE(&bridge->channels, participant, entry) { diff --git a/formats/format_pcm.c b/formats/format_pcm.c index 35612c964..4e846d7cf 100644 --- a/formats/format_pcm.c +++ b/formats/format_pcm.c @@ -91,10 +91,7 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext) return NULL; } s->fr.datalen = res; - if (ast_format_cmp(s->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) - *whennext = s->fr.samples = res * 2; - else - *whennext = s->fr.samples = res; + *whennext = s->fr.samples = res; return &s->fr; } @@ -410,16 +407,11 @@ static int au_rewrite(struct ast_filestream *s, const char *comment) static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence) { off_t min, max, cur; - long offset = 0, bytes; + long offset = 0; struct au_desc *desc = fs->_private; min = desc->hdr_size; - if (ast_format_cmp(fs->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) - bytes = sample_offset / 2; - else - bytes = sample_offset; - if ((cur = ftello(fs->f)) < 0) { ast_log(AST_LOG_WARNING, "Unable to determine current position in au filestream %p: %s\n", fs, strerror(errno)); return -1; @@ -436,11 +428,11 @@ static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence) } if (whence == SEEK_SET) - offset = bytes + min; + offset = sample_offset + min; else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) - offset = bytes + cur; + offset = sample_offset + cur; else if (whence == SEEK_END) - offset = max - bytes; + offset = max - sample_offset; if (whence != SEEK_FORCECUR) { offset = (offset > max) ? max : offset; @@ -479,6 +471,23 @@ static off_t au_tell(struct ast_filestream *fs) return offset - desc->hdr_size; } +static struct ast_frame *g722_read(struct ast_filestream *s, int *whennext) +{ + struct ast_frame *f = pcm_read(s, whennext); + *whennext = s->fr.samples = (*whennext * 2); + return f; +} + +static int g722_seek(struct ast_filestream *fs, off_t sample_offset, int whence) +{ + return pcm_seek(fs, sample_offset / 2, whence); +} + +static off_t g722_tell(struct ast_filestream *fs) +{ + return pcm_tell(fs) * 2; +} + static struct ast_format_def alaw_f = { .name = "alaw", .exts = "alaw|al|alw", @@ -510,10 +519,10 @@ static struct ast_format_def g722_f = { .name = "g722", .exts = "g722", .write = pcm_write, - .seek = pcm_seek, + .seek = g722_seek, .trunc = pcm_trunc, - .tell = pcm_tell, - .read = pcm_read, + .tell = g722_tell, + .read = g722_read, .buf_size = (BUF_SIZE * 2) + AST_FRIENDLY_OFFSET, }; diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h index c2d5a8877..0a5550b5e 100644 --- a/include/asterisk/stream.h +++ b/include/asterisk/stream.h @@ -78,20 +78,6 @@ enum ast_stream_state { }; /*! - * \brief Stream data slots - */ -enum ast_stream_data_slot { - /*! - * \brief Data slot for RTP instance - */ - AST_STREAM_DATA_RTP_CODECS = 0, - /*! - * \brief Controls the size of the data pointer array - */ - AST_STREAM_DATA_SLOT_MAX -}; - -/*! * \brief Create a new media stream representation * * \param name A name for the stream @@ -239,32 +225,47 @@ const char *ast_stream_state2str(enum ast_stream_state state); enum ast_stream_state ast_stream_str2state(const char *str); /*! - * \brief Get the opaque stream data + * \brief Get a stream metadata value * * \param stream The media stream - * \param slot The data slot to retrieve + * \param m_key An arbitrary metadata key * - * \retval non-NULL success - * \retval NULL failure + * \retval non-NULL metadata value + * \retval NULL failure or not found * - * \since 15 + * \since 15.5 */ -void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot); +const char *ast_stream_get_metadata(const struct ast_stream *stream, + const char *m_key); /*! - * \brief Set the opaque stream data + * \brief Get all stream metadata keys * * \param stream The media stream - * \param slot The data slot to set - * \param data Opaque data - * \param data_free_fn Callback to free data when stream is freed. May be NULL for no action. * - * \return data + * \retval An ast_variable list of the metadata key/value pairs. + * \retval NULL if error or no variables are set. * - * \since 15 + * When you're finished with the list, you must call + * ast_variables_destroy(list); + * + * \since 15.5 + */ +struct ast_variable *ast_stream_get_metadata_list(const struct ast_stream *stream); + +/*! + * \brief Set a stream metadata value + * + * \param stream The media stream + * \param m_key An arbitrary metadata key + * \param value String metadata value or NULL to remove existing value + * + * \retval -1 failure + * \retval 0 success + * + * \since 15.5 */ -void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot slot, - void *data, ast_stream_data_free_fn data_free_fn); +int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value); /*! * \brief Get the position of the stream in the topology @@ -278,6 +279,27 @@ void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot s int ast_stream_get_position(const struct ast_stream *stream); /*! + * \brief Get rtp_codecs associated with the stream + * + * \param stream The media stream + * + * \return The rtp_codecs + * + * \since 15.5 + */ +struct ast_rtp_codecs *ast_stream_get_rtp_codecs(const struct ast_stream *stream); + +/*! + * \brief Set rtp_codecs associated with the stream + * + * \param stream The media stream + * \param rtp_codecs The rtp_codecs + * + * \since 15.5 + */ +void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs *rtp_codecs); + +/*! * \brief Create a stream topology * * \retval non-NULL success diff --git a/main/Makefile b/main/Makefile index bef70e966..393ad1aa4 100644 --- a/main/Makefile +++ b/main/Makefile @@ -135,7 +135,8 @@ endif $(ECHO_PREFIX) echo " [FLEX] $< -> $@" $(CMD_PREFIX) $(FLEX) -o $@ ast_expr2.fl $(CMD_PREFIX) sed 's@#if __STDC_VERSION__ >= 199901L@#if !defined __STDC_VERSION__ || __STDC_VERSION__ >= 199901L@' $@ > $@.fix - $(CMD_PREFIX) echo "#include \"asterisk.h\"" > $@ + $(CMD_PREFIX) echo "#define ASTMM_LIBC ASTMM_REDIRECT" > $@ + $(CMD_PREFIX) echo "#include \"asterisk.h\"" >> $@ $(CMD_PREFIX) echo >> $@ $(CMD_PREFIX) cat $@.fix >> $@ $(CMD_PREFIX) rm $@.fix diff --git a/main/cli.c b/main/cli.c index 5730be17b..cf51d0d95 100644 --- a/main/cli.c +++ b/main/cli.c @@ -1614,19 +1614,29 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar ast_str_append(&output, 0, " -- Streams --\n"); for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) { struct ast_stream *stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num); + struct ast_variable *metadata = ast_stream_get_metadata_list(stream); ast_str_append(&output, 0, "Name: %s\n" " Type: %s\n" " State: %s\n" " Group: %d\n" - " Formats: %s\n", + " Formats: %s\n" + " Metadata:\n", ast_stream_get_name(stream), ast_codec_media_type2str(ast_stream_get_type(stream)), ast_stream_state2str(ast_stream_get_state(stream)), ast_stream_get_group(stream), ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf) ); + + if (metadata) { + struct ast_variable *v; + for(v = metadata; v; v = v->next) { + ast_str_append(&output, 0, " %s: %s\n", v->name, v->value); + } + ast_variables_destroy(metadata); + } } ast_channel_unlock(chan); diff --git a/main/sdp.c b/main/sdp.c index 7e283ebf8..e5c8803d5 100644 --- a/main/sdp.c +++ b/main/sdp.c @@ -848,8 +848,7 @@ static struct ast_stream *get_stream_from_m(const struct ast_sdp_a_lines *a_line ast_free(codecs); return NULL; } - ast_stream_set_data(stream, AST_STREAM_DATA_RTP_CODECS, codecs, - (ast_stream_data_free_fn) rtp_codecs_free); + ast_stream_set_rtp_codecs(stream, codecs); if (!m_line->port) { /* Stream is declined. There may not be any attributes. */ diff --git a/main/sdp_state.c b/main/sdp_state.c index 5f9ad5eb9..e02227755 100644 --- a/main/sdp_state.c +++ b/main/sdp_state.c @@ -1732,7 +1732,7 @@ static void merge_remote_stream_capabilities( case AST_MEDIA_TYPE_AUDIO: case AST_MEDIA_TYPE_VIDEO: ao2_bump(joint_state_stream->rtp); - codecs = ast_stream_get_data(remote_stream, AST_STREAM_DATA_RTP_CODECS); + codecs = ast_stream_get_rtp_codecs(remote_stream); ast_assert(codecs != NULL); if (sdp_state->role == SDP_ROLE_ANSWERER) { /* @@ -1789,7 +1789,7 @@ static int create_remote_stream_capabilities( * Setup rx payload type mapping to prefer the mapping * from the peer that the RFC says we SHOULD use. */ - codecs = ast_stream_get_data(remote_stream, AST_STREAM_DATA_RTP_CODECS); + codecs = ast_stream_get_rtp_codecs(remote_stream); ast_assert(codecs != NULL); ast_rtp_codecs_payloads_xover(codecs, codecs, NULL); ast_rtp_codecs_payloads_copy(codecs, diff --git a/main/stream.c b/main/stream.c index 61eef2504..dd3e765f6 100644 --- a/main/stream.c +++ b/main/stream.c @@ -34,6 +34,15 @@ #include "asterisk/strings.h" #include "asterisk/format.h" #include "asterisk/format_cap.h" +#include "asterisk/vector.h" +#include "asterisk/config.h" +#include "asterisk/rtp_engine.h" + +struct ast_stream_metadata_entry { + size_t length; + int value_start; + char name_value[0]; +}; struct ast_stream { /*! @@ -57,19 +66,19 @@ struct ast_stream { enum ast_stream_state state; /*! - * \brief Opaque stream data + * \brief Stream metadata vector */ - void *data[AST_STREAM_DATA_SLOT_MAX]; + struct ast_variable *metadata; /*! - * \brief What to do with data when the stream is freed + * \brief The group that the stream is part of */ - ast_stream_data_free_fn data_free_fn[AST_STREAM_DATA_SLOT_MAX]; + int group; /*! - * \brief The group that the stream is part of + * \brief The rtp_codecs used by the stream */ - int group; + struct ast_rtp_codecs *rtp_codecs; /*! * \brief Name for the stream within the context of the channel it is on @@ -105,7 +114,6 @@ struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char { struct ast_stream *new_stream; size_t stream_size; - int idx; const char *stream_name; if (!stream) { @@ -126,27 +134,23 @@ struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char ao2_ref(new_stream->formats, +1); } - /* We cannot clone the opaque data because we don't know how. */ - for (idx = 0; idx < AST_STREAM_DATA_SLOT_MAX; ++idx) { - new_stream->data[idx] = NULL; - new_stream->data_free_fn[idx] = NULL; - } + new_stream->metadata = ast_stream_get_metadata_list(stream); + + /* rtp_codecs aren't cloned */ return new_stream; } void ast_stream_free(struct ast_stream *stream) { - int i; - if (!stream) { return; } - for (i = 0; i < AST_STREAM_DATA_SLOT_MAX; i++) { - if (stream->data_free_fn[i]) { - stream->data_free_fn[i](stream->data[i]); - } + ast_variables_destroy(stream->metadata); + + if (stream->rtp_codecs) { + ast_rtp_codecs_payloads_destroy(stream->rtp_codecs); } ao2_cleanup(stream->formats); @@ -238,22 +242,81 @@ enum ast_stream_state ast_stream_str2state(const char *str) return AST_STREAM_STATE_REMOVED; } -void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot) +const char *ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key) { - ast_assert(stream != NULL); + struct ast_variable *v; + + ast_assert_return(stream != NULL, NULL); + ast_assert_return(m_key != NULL, NULL); - return stream->data[slot]; + for (v = stream->metadata; v; v = v->next) { + if (strcmp(v->name, m_key) == 0) { + return v->value; + } + } + + return NULL; } -void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot slot, - void *data, ast_stream_data_free_fn data_free_fn) +struct ast_variable *ast_stream_get_metadata_list(const struct ast_stream *stream) { - ast_assert(stream != NULL); + struct ast_variable *v; + struct ast_variable *vout = NULL; + + ast_assert_return(stream != NULL, NULL); + + for (v = stream->metadata; v; v = v->next) { + struct ast_variable *vt = ast_variable_new(v->name, v->value, ""); + + if (!vt) { + ast_variables_destroy(vout); + return NULL; + } + + ast_variable_list_append(&vout, vt); + } - stream->data[slot] = data; - stream->data_free_fn[slot] = data_free_fn; + return vout; +} - return data; +int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value) +{ + struct ast_variable *v; + struct ast_variable *prev; + + ast_assert_return(stream != NULL, -1); + ast_assert_return(m_key != NULL, -1); + + prev = NULL; + v = stream->metadata; + while(v) { + struct ast_variable *next = v->next; + if (strcmp(v->name, m_key) == 0) { + if (prev) { + prev->next = next; + } else { + stream->metadata = next; + } + ast_free(v); + break; + } else { + prev = v; + } + v = next; + } + + if (!value) { + return 0; + } + + v = ast_variable_new(m_key, value, ""); + if (!v) { + return -1; + } + + ast_variable_list_append(&stream->metadata, v); + + return 0; } int ast_stream_get_position(const struct ast_stream *stream) @@ -263,6 +326,24 @@ int ast_stream_get_position(const struct ast_stream *stream) return stream->position; } +struct ast_rtp_codecs *ast_stream_get_rtp_codecs(const struct ast_stream *stream) +{ + ast_assert(stream != NULL); + + return stream->rtp_codecs; +} + +void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs *rtp_codecs) +{ + ast_assert(stream != NULL); + + if (stream->rtp_codecs) { + ast_rtp_codecs_payloads_destroy(rtp_codecs); + } + + stream->rtp_codecs = rtp_codecs; +} + #define TOPOLOGY_INITIAL_STREAM_COUNT 2 struct ast_stream_topology *ast_stream_topology_alloc(void) { diff --git a/menuselect/Makefile b/menuselect/Makefile index c2c9373f4..d949efd55 100644 --- a/menuselect/Makefile +++ b/menuselect/Makefile @@ -24,6 +24,14 @@ endif OBJS:=menuselect.o strcompat.o CFLAGS+=-g -D_GNU_SOURCE -Wall +ifneq ($(findstring dragonfly,$(OSARCH)),) + CFLAGS += -isystem /usr/local/include +else ifneq ($(findstring netbsd,$(OSARCH)),) + CFLAGS += -isystem /usr/pkg/include +else ifneq ($(findstring bsd,$(OSARCH)),) + CFLAGS += -isystem /usr/local/include +endif + ifeq ($(MENUSELECT_DEBUG),yes) CFLAGS += -DMENUSELECT_DEBUG endif diff --git a/menuselect/autoconfig.h.in b/menuselect/autoconfig.h.in index 3e1e18990..f1745516b 100644 --- a/menuselect/autoconfig.h.in +++ b/menuselect/autoconfig.h.in @@ -3,10 +3,6 @@ #ifndef MENUSELECT_AUTOCONFIG_H #define MENUSELECT_AUTOCONFIG_H -#ifndef _REENTRANT -#define _REENTRANT -#endif - /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. diff --git a/menuselect/configure b/menuselect/configure index a0aa10928..7cbe47756 100755 --- a/menuselect/configure +++ b/menuselect/configure @@ -2320,33 +2320,18 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac HOST_OS=${host_os} -PBX_WINARCH=0 case "${host_os}" in - freebsd*) - OSARCH=FreeBSD + *dragonfly*) + CPPFLAGS="${CPPFLAGS} -I/usr/local/include" + LDFLAGS="${LDFLAGS} -L/usr/local/lib" ;; - netbsd*) - OSARCH=NetBSD + *netbsd*) + CPPFLAGS="${CPPFLAGS} -I/usr/pkg/include" + LDFLAGS="${LDFLAGS} -L/usr/pkg/lib" ;; - openbsd*) - OSARCH=OpenBSD - ;; - solaris*) - OSARCH=SunOS - ;; - mingw32) - OSARCH=mingw32 - PBX_WINARCH=1 - ;; - cygwin) - OSARCH=cygwin - PBX_WINARCH=1 - ;; - linux-gnueabi) - OSARCH=linux-gnu - ;; - *) - OSARCH=${host_os} + *bsd*) + CPPFLAGS="${CPPFLAGS} -I/usr/local/include" + LDFLAGS="${LDFLAGS} -L/usr/local/lib" ;; esac diff --git a/menuselect/configure.ac b/menuselect/configure.ac index 2dd4ed652..4a2d0acc2 100644 --- a/menuselect/configure.ac +++ b/menuselect/configure.ac @@ -1,5 +1,3 @@ -# Process this file with autoconf to produce a configure script. - AC_PREREQ(2.59) m4_define([MENUSELECT_VERSION], @@ -16,49 +14,29 @@ AC_CONFIG_HEADER(autoconfig.h) AC_COPYRIGHT("Menuselect") -AC_CANONICAL_BUILD AC_CANONICAL_HOST HOST_OS=${host_os} AC_SUBST(HOST_OS) -PBX_WINARCH=0 case "${host_os}" in - freebsd*) - OSARCH=FreeBSD - ;; - netbsd*) - OSARCH=NetBSD - ;; - openbsd*) - OSARCH=OpenBSD - ;; - solaris*) - OSARCH=SunOS + *dragonfly*) + CPPFLAGS="${CPPFLAGS} -I/usr/local/include" + LDFLAGS="${LDFLAGS} -L/usr/local/lib" ;; - mingw32) - OSARCH=mingw32 - PBX_WINARCH=1 + *netbsd*) + CPPFLAGS="${CPPFLAGS} -I/usr/pkg/include" + LDFLAGS="${LDFLAGS} -L/usr/pkg/lib" ;; - cygwin) - OSARCH=cygwin - PBX_WINARCH=1 - ;; - linux-gnueabi) - OSARCH=linux-gnu - ;; - *) - OSARCH=${host_os} + *bsd*) + CPPFLAGS="${CPPFLAGS} -I/usr/local/include" + LDFLAGS="${LDFLAGS} -L/usr/local/lib" ;; esac AH_TOP( #ifndef MENUSELECT_AUTOCONFIG_H #define MENUSELECT_AUTOCONFIG_H - -#ifndef _REENTRANT -#define _REENTRANT -#endif ) AH_BOTTOM([#endif]) diff --git a/res/Makefile b/res/Makefile index ecaa03d3c..ec3417b35 100644 --- a/res/Makefile +++ b/res/Makefile @@ -45,7 +45,8 @@ endif $(ECHO_PREFIX) echo " [FLEX] $< -> $@" $(CMD_PREFIX) (cd ael; $(FLEX) ael.flex) $(CMD_PREFIX) sed 's@#if __STDC_VERSION__ >= 199901L@#if !defined __STDC_VERSION__ || __STDC_VERSION__ >= 199901L@' $@ > $@.fix - $(CMD_PREFIX) echo "#include \"asterisk.h\"" > $@ + $(CMD_PREFIX) echo "#define ASTMM_LIBC ASTMM_REDIRECT" > $@ + $(CMD_PREFIX) echo "#include \"asterisk.h\"" >> $@ $(CMD_PREFIX) echo >> $@ $(CMD_PREFIX) cat $@.fix >> $@ $(CMD_PREFIX) rm $@.fix diff --git a/tests/test_stream.c b/tests/test_stream.c index 8c887048c..50f0ccbfd 100644 --- a/tests/test_stream.c +++ b/tests/test_stream.c @@ -38,6 +38,7 @@ #include "asterisk/format_cap.h" #include "asterisk/format_cache.h" #include "asterisk/channel.h" +#include "asterisk/uuid.h" AST_TEST_DEFINE(stream_create) { @@ -224,6 +225,70 @@ AST_TEST_DEFINE(stream_set_state) return AST_TEST_PASS; } +AST_TEST_DEFINE(stream_metadata) +{ + RAII_VAR(struct ast_stream *, stream, NULL, ast_stream_free); + char track_label[AST_UUID_STR_LEN + 1]; + const char *stream_track_label; + int rc; + + switch (cmd) { + case TEST_INIT: + info->name = "stream_metadata"; + info->category = "/main/stream/"; + info->summary = "stream metadata unit test"; + info->description = + "Test that metadata operations on a stream works"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + stream = ast_stream_alloc("test", AST_MEDIA_TYPE_AUDIO); + if (!stream) { + ast_test_status_update(test, "Failed to create media stream given proper arguments\n"); + return AST_TEST_FAIL; + } + + stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL"); + if (stream_track_label) { + ast_test_status_update(test, "New stream HAD a track label\n"); + return AST_TEST_FAIL; + } + + ast_uuid_generate_str(track_label, sizeof(track_label)); + rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", track_label); + if (rc != 0) { + ast_test_status_update(test, "Failed to add track label\n"); + return AST_TEST_FAIL; + } + + stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL"); + if (!stream_track_label) { + ast_test_status_update(test, "Changed stream does not have a track label\n"); + return AST_TEST_FAIL; + } + + if (strcmp(stream_track_label, track_label) != 0) { + ast_test_status_update(test, "Changed stream did not return same track label\n"); + return AST_TEST_FAIL; + } + + rc = ast_stream_set_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL", NULL); + if (rc != 0) { + ast_test_status_update(test, "Failed to remove track label\n"); + return AST_TEST_FAIL; + } + + stream_track_label = ast_stream_get_metadata(stream, "AST_STREAM_METADATA_TRACK_LABEL"); + if (stream_track_label) { + ast_test_status_update(test, "Changed stream still had a track label after we removed it\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + AST_TEST_DEFINE(stream_topology_create) { RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free); @@ -254,6 +319,11 @@ AST_TEST_DEFINE(stream_topology_clone) RAII_VAR(struct ast_stream_topology *, topology, NULL, ast_stream_topology_free); RAII_VAR(struct ast_stream_topology *, cloned, NULL, ast_stream_topology_free); struct ast_stream *audio_stream, *video_stream; + char audio_track_label[AST_UUID_STR_LEN + 1]; + char video_track_label[AST_UUID_STR_LEN + 1]; + const char *original_track_label; + const char *cloned_track_label; + int rc; switch (cmd) { case TEST_INIT: @@ -279,6 +349,13 @@ AST_TEST_DEFINE(stream_topology_clone) return AST_TEST_FAIL; } + ast_uuid_generate_str(audio_track_label, sizeof(audio_track_label)); + rc = ast_stream_set_metadata(audio_stream, "AST_STREAM_METADATA_TRACK_LABEL", audio_track_label); + if (rc != 0) { + ast_test_status_update(test, "Failed to add track label\n"); + return AST_TEST_FAIL; + } + if (ast_stream_topology_append_stream(topology, audio_stream) == -1) { ast_test_status_update(test, "Failed to append valid audio stream to stream topology\n"); ast_stream_free(audio_stream); @@ -291,6 +368,13 @@ AST_TEST_DEFINE(stream_topology_clone) return AST_TEST_FAIL; } + ast_uuid_generate_str(video_track_label, sizeof(video_track_label)); + rc = ast_stream_set_metadata(video_stream, "AST_STREAM_METADATA_TRACK_LABEL", video_track_label); + if (rc != 0) { + ast_test_status_update(test, "Failed to add track label\n"); + return AST_TEST_FAIL; + } + if (ast_stream_topology_append_stream(topology, video_stream) == -1) { ast_test_status_update(test, "Failed to append valid video stream to stream topology\n"); ast_stream_free(video_stream); @@ -313,11 +397,45 @@ AST_TEST_DEFINE(stream_topology_clone) return AST_TEST_FAIL; } + original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 0), + "AST_STREAM_METADATA_TRACK_LABEL"); + if (!original_track_label) { + ast_test_status_update(test, "Original topology stream 0 does not contain metadata\n"); + return AST_TEST_FAIL; + } + cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 0), + "AST_STREAM_METADATA_TRACK_LABEL"); + if (!cloned_track_label) { + ast_test_status_update(test, "Cloned topology stream 0 does not contain metadata\n"); + return AST_TEST_FAIL; + } + if (strcmp(original_track_label, cloned_track_label) != 0) { + ast_test_status_update(test, "Cloned topology stream 0 track label was not the same as the original\n"); + return AST_TEST_FAIL; + } + if (ast_stream_get_type(ast_stream_topology_get_stream(cloned, 1)) != ast_stream_get_type(ast_stream_topology_get_stream(topology, 1))) { ast_test_status_update(test, "Cloned video stream does not contain same type as original\n"); return AST_TEST_FAIL; } + original_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(topology, 1), + "AST_STREAM_METADATA_TRACK_LABEL"); + if (!original_track_label) { + ast_test_status_update(test, "Original topology stream 1 does not contain metadata\n"); + return AST_TEST_FAIL; + } + cloned_track_label = ast_stream_get_metadata(ast_stream_topology_get_stream(cloned, 1), + "AST_STREAM_METADATA_TRACK_LABEL"); + if (!cloned_track_label) { + ast_test_status_update(test, "Cloned topology stream 1 does not contain metadata\n"); + return AST_TEST_FAIL; + } + if (strcmp(original_track_label, cloned_track_label) != 0) { + ast_test_status_update(test, "Cloned topology stream 1 track label was not the same as the original\n"); + return AST_TEST_FAIL; + } + return AST_TEST_PASS; } @@ -2139,6 +2257,7 @@ static int unload_module(void) AST_TEST_UNREGISTER(stream_set_type); AST_TEST_UNREGISTER(stream_set_formats); AST_TEST_UNREGISTER(stream_set_state); + AST_TEST_UNREGISTER(stream_metadata); AST_TEST_UNREGISTER(stream_topology_create); AST_TEST_UNREGISTER(stream_topology_clone); AST_TEST_UNREGISTER(stream_topology_clone); @@ -2169,6 +2288,7 @@ static int load_module(void) AST_TEST_REGISTER(stream_set_type); AST_TEST_REGISTER(stream_set_formats); AST_TEST_REGISTER(stream_set_state); + AST_TEST_REGISTER(stream_metadata); AST_TEST_REGISTER(stream_topology_create); AST_TEST_REGISTER(stream_topology_clone); AST_TEST_REGISTER(stream_topology_append_stream); |